После того, как вы приняли умные указатели boost, есть ли случай, когда вы используете сырые указатели? - PullRequest
12 голосов
/ 12 декабря 2008

Мне любопытно, когда я начинаю принимать больше идиоматических выражений и что является наилучшей практикой. Интересно, в какой момент мой с ++ даже отдаленно похож на с ++ прошлого года, часто встречающийся в типичных примерах и в умах? из тех, кто еще не знаком с "Modern C ++"?

Ответы [ 10 ]

7 голосов
/ 12 декабря 2008

Я почти не использую shared_ptr, потому что вообще избегаю совместного владения. Поэтому я использую что-то вроде boost::scoped_ptr для «владения» объектом, но все остальные ссылки на него будут указателями. Пример:

boost::scoped_ptr<SomeType> my_object(new SomeType);
some_function(my_object.get());

Но some_function будет иметь дело с необработанным указателем:

void some_function(SomeType* some_obj)
{
  assert (some_obj);
  some_obj->whatever();
}
6 голосов
/ 18 декабря 2008

Только несколько от макушки моей головы:

  • Навигация в отображенных в память файлах.
  • Вызовы Windows API, где вам нужно перераспределить (например, LPBITMAPINFOHEADER).
  • Любой код, где вы копаетесь в произвольной памяти (VirtualQuery () и т. П.).
  • Почти каждый раз, когда вы используете reinterpret_cast <> для указателя.
  • Каждый раз, когда вы используете новое место размещения.

Общий поток здесь - это «любая ситуация, в которой вам нужно обрабатывать часть памяти как что-то, кроме ресурса, над которым у вас есть контроль выделения».

4 голосов
/ 12 декабря 2008

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

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

4 голосов
/ 12 декабря 2008

Я считаю, что основным отличием «современного» C ++ от старого * является осторожное использование инвариантов классов и инкапсуляция. Хорошо организованный код имеет тенденцию иметь меньше указателей. Я почти так же нервно плаваю в shared_ptrs, как и в новостях и удалениях.

Я с нетерпением жду unique_ptr в C ++ 0x. Я думаю, что это уберет несколько (умных) указателей, которые все еще бродят в дикой природе.

* все еще, к сожалению, очень распространенный

4 голосов
/ 12 декабря 2008

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

Единственные места, где я не использую указатели, - это пара сценариев взаимодействия с другими базами кода, над которыми я не имею контроля.

2 голосов
/ 12 декабря 2008

Я по-прежнему использую необработанные указатели на устройствах с отображенным в память вводом-выводом, таких как встроенные системы, где наличие интеллектуального указателя на самом деле не имеет смысла, поскольку вам никогда не понадобится или не удастся delete его.

2 голосов
/ 12 декабря 2008

Я все еще использую обычные указатели в чувствительном к ресурсам коде или другом коде, который требует крошечного следа, такого как определенные исключения, где я не могу предположить, что какие-либо данные являются допустимыми, и должен также предположить, что у меня тоже недостаточно памяти.

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

О, и есть еще одно место для использования сырых указателей:

boost::shared_ptr<int> ptr(new int);
1 голос
/ 12 декабря 2008

Я пишу C ++, который должен сосуществовать с Objective C (используя Objective C ++ для соединения). Поскольку объекты C ++, объявленные как часть классов Objective C ++, не имеют названных конструкторов или деструкторов, вы не сможете их удерживать в умных указателях.

Так что я склонен использовать необработанные указатели, хотя часто с boost :: intrustive_ptr и внутренним подсчетом ссылок.

1 голос
/ 12 декабря 2008

Если у вас есть круговые структуры данных, например, A указывает на B, а B указывает на A, вы не можете использовать наивные умные указатели для A и B, поскольку тогда объекты будут освобождены только от дополнительной работы. Чтобы освободить память, вы должны вручную очистить умные указатели, что примерно так же плохо, как удаление, от которого умные указатели избавляются.

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

Требуется некоторая осторожность. Умные указатели не эквивалентны сборке мусора.

0 голосов
/ 13 декабря 2008

Не то чтобы я это делал, но вам нужны необработанные указатели для реализации, скажем, связанного списка или графика. Но было бы намного умнее использовать std::list<> или boost::graph<>.

...