Замена auto_ptr в VC ++ 8 - PullRequest
9 голосов
/ 07 ноября 2008

std::auto_ptr не работает в VC ++ 8 (это то, что мы используем на работе). Мой главный недостаток в том, что он допускает auto_ptr<T> x = new T();, что, конечно, приводит к ужасным сбоям, и в то же время просто сделать по ошибке.

От ответа до другого вопроса здесь на stackoverflow:

Обратите внимание, что реализация std :: auto_ptr в Visual Studio 2005 ужасно нарушена. http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=98871 http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=101842

Я хочу использовать

  • boost::scoped_ptr, для указателей, которые не должны переходить в собственность.
  • boost::shared_ptr, для указателей в контейнерах и в других местах, где они требуются.
  • std::auto_ptr, для указателей, которые должны / могут передать право собственности.

Но так как std::auto_ptr сломан для меня, я думаю, что будет лучшим подходом:

  • Заменить std::auto_ptr чем-то из сети. Как этот этот один от Рани Шарони (еще не пробовал).
  • Используйте взамен boost::shared_ptr. Будет, конечно, работать, хотя будут некоторые незначительные накладные расходы, которые меня не волнуют. Но я хочу использовать auto_ptr для обозначения цели указателя. (См. этот ответ для голосования по этому подходу.)
  • Мне никогда не понадобится передавать право владения на практике, поэтому мне не стоит об этом беспокоиться.

Обновление: Вот что я сделал: Я скопировал вышеупомянутую реализацию auto_ptr Рани Шарони. Отсюда .

Несколько небольших тестов:

class T
{
public:
    T() {
        OutputDebugStringA("T\n");
    };
    ~T() {
        OutputDebugStringA("~T\n");
    };
};

{
    fix::auto_ptr<T> x(new T); // This just works.
}
{
    fix::auto_ptr<T> x = (new T); // Doesn't compile. Great!
}
{
    fix::auto_ptr<T> x = fix::auto_ptr<T>(new T); // Transfer of ownership works also.
}

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

Примечание: я не знаю, разрешено ли мне использовать эту реализацию в отношении авторского права. Я написал Рани по электронной почте, и я жду ответа. Я обновлю этот пост, когда узнаю больше. Каждому разрешено использовать реализацию auto_ptr Рани Шарони по вашему желанию.

Спасибо за все ваши ответы.

Ответы [ 7 ]

7 голосов
/ 07 ноября 2008

Двигайтесь, чтобы повысить умные указатели.

Тем временем вы можете извлечь работающую реализацию auto_ptr из старого / другого STL, чтобы у вас был рабочий код.

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

unique-ptr «исправляет» это, делая релиз не только отказывающимся от владения, но и устанавливая RHS равным нулю. Это самая близкая замена для auto-ptr, но с другой семантикой она не является заменой.

Есть вводная статья, чтобы повысить умные указатели , хм, я.

3 голосов
/ 07 ноября 2008

Рассматривали ли вы использование STLPort ?

2 голосов
/ 07 ноября 2008

Использовать unique_ptr. Я думаю, что они были введены, чтобы быть лучшим auto_ptr.

http://www.boost.org/doc/libs/1_35_0/doc/html/interprocess/interprocess_smart_ptr.html#interprocess.interprocess_smart_ptr.unique_ptr

На самом деле, я считаю, что auto_ptr может быть устаревшим в пользу этого:

http://objectmix.com/c/113487-std-auto_ptr-deprecated.html

1 голос
/ 07 ноября 2008

Почему вы думаете, что std :: auto_ptr <> не работает.

Хотелось бы, чтобы о ком-то плохом было сообщено в комитет стандартов!

Вы имеете в виду, что вам нужно:

std::auto_ptr<T>   x(new T);  // Use the explicit constructor.
0 голосов
/ 06 августа 2009

Не ответ, но для общего интереса любого, для кого эти ошибки актуальны. Есть еще одна связанная ошибка с VC8 auto_ptr, которая связана с неявными повышениями. Это, вероятно, самое большое зло, потому что другие ошибки позволяют компилировать код, который в противном случае является недопустимым в соответствии со стандартом, без сбоев, но, по крайней мере, совместимый код работает нормально. С этой ошибкой код, который на самом деле совместим, не работает должным образом.

Проблема заключается в следующем. Стандарт определяет конструкторы auto_ptr и операторы преобразования таким образом, что они поддерживают неявное преобразование auto_ptr s, как и в случае с обычными указателями. Однако реализация VC8 этого делает reinterpret_cast, а не static_cast. Естественно, не только это У.Б. на букву стандарта, но он также разрывается с несколькими базовыми классами и / или виртуальным наследованием. Вот пример юридического кода, нарушенного этим:

struct Base1 { int x; };
struct Base2 { int y; };
struct Derived : Base1, Base2 {};

std::auto_ptr<Derived> createDerived()
{
  return std::auto_ptr<Derived>(new Derived);
}

std::auto_ptr<Base2> base2(createDerived());

На одном из моих прошлых заданий, когда мы столкнулись с этой проблемой на производстве, мы в итоге просто сами залатали заголовки (это тривиальное исправление в две строки).

0 голосов
/ 06 августа 2009

Насколько я помню, не так ли:

auto_ptr<T> x = auto_ptr<T>(new T()); ??
0 голосов
/ 07 ноября 2008

Используйте boost :: shared_ptr / boost :: scoped_ptr. Это будет предпочтительный интеллектуальный указатель в будущих стандартах C ++ (уже в TR1).

Edit: Пожалуйста, найдите соответствующее обсуждение здесь: Идиоматическое использование std :: auto_ptr или только использование shared_ptr?

...