Почему библиотеки и фреймворки C ++ никогда не используют умные указатели?

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

Однако я заметил, что фреймворки, такие как Qt, wxWidgets и библиотеки, такие как Boost, никогда не возвращают и не ожидают интеллектуальных указателей, как если бы они вообще не использовали их. Вместо этого они возвращаются или ожидают сырых указателей. Есть ли причина для этого? Должен ли я держаться подальше от умных указателей при написании общедоступного API и почему?

Просто интересно, почему умные указатели рекомендуются, когда многие крупные проекты их избегают.

 R. Martinho Fernandes26 апр. 2012 г., 15:57
Действительно, мобильные телефоны работают под управлением Java.
 Puppy26 апр. 2012 г., 15:43
@EdHeal: причина, по которой вы чувствуете, как пламя лижет ваши ноги, заключается в том, что вы абсолютно неправы во всех отношениях. Например, какие накладные расходы есть вunique_ptr? Никак нет. Предназначены ли Qt / WxWidgets для встроенных систем или систем реального времени? Нет, они предназначены для Windows / Mac / Unix на настольном компьютере - максимум. Умные указатели предназначены для программистов, которые хотят, чтобы это было правильно.
 chrisaycock26 апр. 2012 г., 15:33
Все те библиотеки, которые вы только что назвали, были созданы много лет назад. Умные указатели стали по-настоящему стандартными в C ++ 11.
 Kaz26 апр. 2012 г., 22:03
Умные указатели только действительно стандартны в C ++ 11? Какие??? Эти вещи используются уже более 20 лет.
 Ed Heal26 апр. 2012 г., 15:37
Интеллектуальные указатели имеют накладные расходы (подсчет ссылок и т. д.), которые могут быть критическими, например, во встроенных системах / системах реального времени. ИМХО - умные указатели для ленивых программистов. Также много API-интерфейсов идут для наименьшего общего знаменателя. Я чувствую, как пламя лижет мои ноги, когда я печатаю!

Ответы на вопрос(8)

в какой области вы работаете. Я пишу игровые движки для жизни, мы избегаем ускорения, как чумы, в играх накладные расходы ускорения неприемлемы. В нашем основном движке мы закончили тем, что написали собственную версию stl (очень похожую на ea stl).

Если бы я написал приложение для форм, я мог бы подумать об использовании умных указателей; но как только управление памятью становится второй натурой, отсутствие детального контроля над памятью становится довольно раздражающим.

 19 мая 2013 г., 23:10
Я никогда не делал так, чтобы shared_ptr замедлял мой игровой движок до какой-либо заслуживающей внимания степени. Они ускорили процесс производства и отладки. Кроме того, что именно вы имеете в виду под "издержками повышения?" Это довольно большое одеяло.
 19 мая 2013 г., 17:44
Не существует такой вещи, как «накладные расходы на повышение».
 09 мая 2015 г., 21:50
@curiousguy: Это издержки компиляции всех этих заголовков и voodoo макроса + шаблона ...

пытаясь стать Java. Я считаю, что сейчас у него действительно есть свои умные указатели, но в целом это едва ли не вершина дизайна. Насколько я знаю, wxWidgets был разработан задолго до того, как были написаны полезные умные указатели.

Что касается Boost, я полностью ожидаю, что они используют умные указатели, где это уместно. Возможно, вам придется быть более конкретным.

Кроме того, не забывайте, что существуют умные указатели для обеспечения прав собственности. Если у API нет семантики владения, зачем использовать умный указатель?

 26 апр. 2012 г., 15:43
Qt был написан до того, как большая часть функциональности была достаточно широко распространена на платформах, которые он хотел использовать. У него были умные указатели в течение долгого времени, и он использует их для неявного совместного использования ресурсов почти во всех классах Q *.
 26 апр. 2012 г., 21:43
Every Библиотека GUI без необходимости заново изобретает колесо. Даже строки, Qt имеетQString, wxWidgets имеетwxString, MFC ужасно названCString, Не является ли UTF-8std::string достаточно для 99% задач с графическим интерфейсом?
 02 авг. 2012 г., 15:40
@Inverse QString был создан, когда не было std :: string.
 08 янв. 2013 г., 07:11
Проверьте, когда был создан qt и какие умные указатели были доступны в то время.

Smart pointers became part of standard just recently. Till then they were part of other libraries Their primary use is to avoid memory leaks; many libraries don't have their own memory management; Generally they provide utilities and APIs They are implemented as wrapper, since they are actually objects and not pointers. Which has additional time/space cost, compared to raw pointers; The users of the libraries may not want to have such overheads

EditИспользование интеллектуальных указателей полностью зависит от разработчика. Это зависит от различных факторов.

In performance critical systems, you may not want to use smart pointers which generates overhead

The project which needs the backward compatibility, you may not want to use the smart pointers which has C++11 specific features

Edit2 Из-за нижнего прохода в течение 24 часов есть ряд отрицательных голосов. Я не понимаю, почему за этот ответ проголосовали, хотя ниже приведено лишь дополнительное предложение, а не ответ.
Тем не менее, C ++ всегда облегчает вам открывать опции. :) например

template<typename T>
struct Pointer {
#ifdef <Cpp11>
  typedef std::unique_ptr<T> type;
#else
  typedef T* type;
#endif
};

И в вашем коде используйте его как:

Pointer<int>::type p;

Для тех, кто говорит, что умный указатель и необработанный указатель разные, я согласен с этим. Код выше был простоidea где можно написать код, который является взаимозаменяемым только с#define, это неcompulsion;

Например,T* должен быть удален явно, а умный указатель - нет. Мы можем иметь шаблонDestroy() справиться с этим.

template<typename T>
void Destroy (T* p)
{
  delete p;
}
template<typename T>
void Destroy (std::unique_ptr<T> p)
{
  // do nothing
}

и использовать его как:

Destroy(p);

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

Pointer<X>::type p = new X;
Pointer<X>::type p2(Assign(p));

кудаAssign() как есть:

template<typename T>
T* Assign (T *p)
{
  return p;
}
template<typename T>
... Assign (SmartPointer<T> &p)
{
  // use move sematics or whateve appropriate
}
 06 янв. 2013 г., 09:58
Вы не можете печатать так, эти типы никоим образом не эквивалентны. Написание typedefs напрашивается на неприятности.
 this.lau_29 апр. 2012 г., 10:43
@iammilind, это интересные моменты, но забавно то, что если мы в конечном итоге будем использовать умные указатели, как, по-видимому, многие рекомендовали бы, мы в конечном итоге создадим код, несовместимый с основными библиотеками. Конечно, мы можем оборачивать / разворачивать умные указатели по мере необходимости, но это создает много хлопот и создает непоследовательный код (иногда мы имеем дело с умными указателями, иногда нет).
 06 янв. 2013 г., 06:17
Утверждение, что умные указатели имеют «дополнительные затраты времени / пространства» несколько вводит в заблуждение; все умные указатели, кромеunique_ptr понести затраты времени выполнения, ноunique_ptr является наиболее часто используемым. Пример кода, который вы предоставляете, также вводит в заблуждение, потому чтоunique_ptr а такжеT* это совершенно разные понятия. Тот факт, что вы относитесь к ним обоим какtype создается впечатление, что их можно обменять друг на друга.
 26 апр. 2012 г., 16:13
На 3.Some умные указатели имеют дополнительные затраты времени / пространства, другие не включают, в том числеstd::auto_ptr это было частью стандарта в течение длительного времени (и обратите внимание, мне нравитсяstd::auto_ptr как возвращаемый тип для функций, создающих объекты, даже если он почти бесполезен везде). В С ++ 11std::unique_ptr не имеет никаких дополнительных затрат по сравнению с простым указателем.
 26 апр. 2012 г., 17:30
Точно ... есть приятная симметрия на внешний видunique_ptr и исчезновениеauto_ptrкод, ориентированный на C ++ 03, должен использовать более позднюю версию, тогда как код, нацеленный на C ++ 11, может использовать первую. Умные указателиnot shared_ptrЕсть много стандартных и ни одного стандарта, включая предложения к стандарту, которые были отклонены какmanaged_ptr
Решение Вопроса

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

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

Но из-за отсутствия стандартного ABI вы вообщеcannot передать эти объекты безопасно через границы модуля. GCCshared_ptr вероятно, отличается от MSVCshared_ptr, который тоже может отличаться от Intelshared_ptr, Даже сsame компилятор, эти классы не гарантированно двоично совместимы между версиями.

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

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

Небиблиотечный код должен, однако, обычно предпочитать умные указатели необработанным.

 27 апр. 2012 г., 11:16
@josefx: Да, это печально, но это правда, единственная альтернатива - это COM или необработанный интерфейс C. Я хотел бы, чтобы C ++ начал беспокоиться о подобных проблемах. Я имею в виду, что С ++ не является новым языком 2 года назад.
 27 апр. 2012 г., 10:17
Суть заключается в следующем: если вы хотите распространять предварительно собранную версию, вы должны делать это для каждого компилятора, который вы хотите поддерживать.
 13 сент. 2013 г., 08:06
@NathanAdams: Такое программное обеспечение, несомненно, впечатляет и полезно. Но это относится к симптому более глубоких проблем: семантика C ++ времени жизни и владения где-то между бедной и несуществующей. Эти кучи ошибок не возникли бы, если бы язык не позволял им. Так что умные указатели - это не панацея, а попытка возместить некоторые потери, понесенные в первую очередь при использовании C ++.
 06 июл. 2013 г., 14:09
Я понизил голос, потому что это неправильно. Проблемы ABI более чем управляемы в большинстве случаев. Несмотря на то, что ABI едва ли удобна для пользователя, она также вряд ли является непреодолимой
 27 апр. 2012 г., 07:56
Я согласен с вами, даже передача std :: string может быть проблематичной. Это многое говорит о C ++ как о "отличном языке для библиотек".

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

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

Интеграция с C - еще одна проблема.

Другая проблема заключается в том, что умные указатели являются частью STL. C ++ предназначен для использования без STL.

 19 мая 2013 г., 17:48
& Quot;Another issue is smart pointers are part of the STL.& Quot; Они не.

non-standards, so each library tend to reinvent its own (NIH syndrom & dependencies issues) potential cost

default умный указатель, в том, что это бесплатно, являетсяunique_ptr, К сожалению, это требует семантики перемещения C ++ 11, которая появилась только недавно. Все остальные умные указатели имеют стоимость (shared_ptr, intrusive_ptr) или имеют менее чем идеальную семантику (auto_ptr).

С C ++ 11 за углом, приносяstd::unique_ptrМожно было бы подумать, что это наконец закончилось ... Я не так оптимистичен.

Лишь несколько крупных компиляторов реализуют большую часть C ++ 11 и только в своих последних версиях. Мы можем ожидать, что основные библиотеки, такие как QT и Boost, будут некоторое время сохранять совместимость с C ++ 03, что несколько препятствует широкому внедрению новых и блестящих интеллектуальных указателей.

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

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

Я мог бы взять в качестве примера библиотеку, над которой мы работали, где после нескольких месяцев разработки я понял, что мы использовали указатели и умные указатели только в нескольких классах (3-5% всех классов).

Переходяvariables by reference в большинстве мест было достаточно, мы использовали умные указатели всякий раз, когда у нас был объект, который мог быть нулевым, и необработанные указатели, когда нас заставляла библиотека, которую мы использовали.

Edit (Я не могу комментировать из-за своей репутации): Передача переменных по ссылке очень гибкая: если вы хотите, чтобы объект был доступен только для чтения, вы можете использовать константную ссылку (вы все равно можете сделать несколько неприятных приведений, чтобы иметь возможность писать объект), но вы получаете максимально возможную защиту (это то же самое с умными указателями). Но я согласен, что гораздо приятнее просто вернуть объект.

 26 апр. 2012 г., 16:17
у вас есть const для этого (кажется, я могу комментировать: D).
 26 апр. 2012 г., 16:09
Я не согласен с вами, но я укажу, что существует школа мысли, которая не одобряетvariable ссылки в большинстве случаев. Признаюсь, я придерживаюсь этой школы. Я предпочитаю функции не изменять свои аргументы. Во всяком случае, насколько мне известно, ссылки на переменные в C ++ ничего не делают для предотвращения неправильного обращения с объектами, на которые они ссылаются, что и намерены делать умные указатели.

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

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

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

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

Update:  Комментатор правильно заметил, что C ++ новыйunique_ptr (доступно с TR1) не учитывает ссылки. Комментатор также имеет другое определение «умный указатель»; чем я имею в виду. Он может быть прав насчет определения.

Further update:  Приведенная ниже цепочка комментариев освещает. Все это рекомендуется к прочтению.

 26 апр. 2012 г., 16:04
shared_ptr не имеет накладных расходов. Он имеет накладные расходы только в том случае, если вам не нужна поточно-ориентированная семантика совместного владения, что она и обеспечивает.
 26 апр. 2012 г., 15:54
@EdHeal: не жить без встроенных систем! = Программирование для них - не крошечное, не относящееся к делу меньшинство. Умные указатели подходят для любой ситуации, в которой вам нужно управлять временем жизни ресурса.
 26 апр. 2012 г., 15:53
@ thb - я согласен с тобой. DeadMG - Пожалуйста, попробуйте жить без встроенных систем. Да - у некоторых умных указателей нет накладных расходов, но у некоторых есть. ОП упоминает библиотеки. Например, в Boost есть компоненты, которые используются встроенными системами, но интеллектуальные указатели могут быть неподходящими для определенных приложений.
 27 апр. 2012 г., 01:22
Нет, shared_ptr имеет значительные накладные расходы по сравнению с минимумом, необходимым для семантики совместного владения потокобезопасными; в частности, он выделяет блок кучи отдельно от фактического объекта, которым вы делитесь, с единственной целью хранения ссылки. intrusive_ptr более эффективен, но (как и shared_ptr) также предполагает, что каждый указатель на объект будет intrusive_ptr. Вы можете получить даже меньшие издержки, чем intrusive_ptr, с помощью общего указателя подсчета ссылок, как я делаю в моем приложении, и затем использовать T * всякий раз, когда вы можете гарантировать, что хотя бы один умный указатель переживет значение T *.
 26 апр. 2012 г., 15:49
Для начала, программирование встраиваемых систем - это огромное меньшинство всего программирования, и оно совершенно неактуально. C ++ - это язык общего назначения. Во-вторых,shared_ptr ведет подсчет ссылок. Существует много других типов интеллектуальных указателей, которые вообще не ведут подсчет ссылок. Наконец, упомянутые библиотеки нацелены на платформы, у которых есть много свободных ресурсов. Не то, чтобы я был downvoter, но все, что я говорю, - то, что Ваш пост полон неправильного.

Ваш ответ на вопрос