2009-04-13 3 views

ответ

12

Да, но более распространенная идиома C++ для этой ситуации заключается в использовании ссылки (и, возможно, const rreference) вместо указателя. Таким образом, вместо

void foo(sometype * p) { 
    p->func(); 
} 

Вы пишете:

void foo(sometype & p) { 
    p.func(); 
} 

Это имеет то преимущество, что вам не нужно разыменования объекта в вызывающей:

void afunc() { 
    sometype t; 
    foo(t); 
} 

, а также дает подсознательное подскажите читателю, что вы не намерены использовать функцию для владения объектом.

+3

"и, возможно, константа-ссылка": const & s велики и должны использоваться по возможности, но всякий раз, когда функция намеревается изменить значение параметра, вы должны передать указатель, а не ссылку, поэтому ясно, что вы намереваетесь изменить параметр. Владелец Mem должен быть хорошо документирован – Tom

+0

+1 для ответа Тома –

10

Если вы уверены, что вызов синхронный, то вполне правильно отправить адрес выделенного объекта стека функции. Если вызов является асинхронным (т. Е. Вызываемая вами функция передает указатель на другой поток), то он определенно создает проблемы, так как вы можете попытаться получить доступ к адресу памяти из другого потока даже после того, как объект, выделенный для стека, будет уничтожен.

+0

Довольно гипотетическую, хотя, как и с обычной C или языка C++ построить один не может вызвать любую функцию асинхронно. Ответ Ассафа гораздо ближе к повседневной жизни. – lothar

+0

lothar - как насчет fork()? Любая нетривиальная программа, все еще работающая в одном потоке, является динозавром. Модифицируйте это. – MaxVT

+0

@MaxVT Вызов fork никоим образом не является методом асинхронного вызова функции, весь ваш процесс дублируется (включая все его данные). – lothar

6

Пока функция приема не предполагает, что она получает право собственности на ресурс (и пытается освободить его), обязательно. Однако ссылка может быть лучшей идеей.

2

Его отлично подходит для синхронного вызова функции. Если вызов асинхронен, это может привести к сбою при удалении объекта стека, когда он выходит из области видимости.

2

Вы должны быть осторожны, чтобы не хранить этот указатель для дальнейшего использования. Например:

void store(int* param) { 
    // Store pointer in some global storage for further use 
    global_storage.add_param(param); 
} 
void func() { 
    int test_var = 5; 
    store(&test_var); // Pass the pointer to the global storage 
} 
// At this point stack object test_var will be destroyed 
// Global storage contains a pointer, that points to some garbage 
1

Это, безусловно, действительно, но со многими оговорками. Вот лучшие вещи, чтобы иметь в виду (некоторые из них уже отмечалось другими, некоторые нет.)

  • Указатель само по себе может означать, что владение ресурсом передается вызываемая (т.е. они должны освободить его после использования) , Здесь имеется ссылка.
  • Во многих ситуациях функция, которую вы должны вызывать, уже определена, и вы не можете ее изменить, вы должны изучить ее поведение и убедиться, что он не предполагает, что он будет владеть объектом, хранить его статически или копировать в другом месте.
  • Если функция, которую вы вызываете, должна принимать нулевой указатель, чтобы указать отсутствие указанного параметра, у вас не будет выбора использования ссылки.
  • Асинхронные вызовы абсолютно нет-нет (если, конечно, вы не блокируете, пока они не будут выполнены с использованием вашего локального объекта, а затем возвращаются).
  • Вызываемая функция никогда не должна в любом случае получать доступ к размеру объекта, о котором идет речь, это уничтожит ваш стек и почти наверняка сбой вашей программы!
  • Вызов функции, которая подвержена доступу к байтам, превышающим размер объекта, может быть ответственностью за безопасность. На деле это самый распространенный метод взлома в безопасных системах. Это называется переполнением буфера.(Выходит за рамки вашего вопроса, но вы можете прочитать больше here и here)