Здравствуйте, Аноним, Вы писали:
А>Не могли бы вы привести маленький примерчик, хорошо иллюстрирующий проблемы применения auto_ptr в STL контейнерах?
auto_ptr нельзя применять в контейнерах. Используй boost::shared_ptr или напиши свой аналог.
Re[2]: auto_ptr и контейнеры
От:
Аноним
Дата:
22.01.03 11:29
Оценка:
Здравствуйте, Lexey, Вы писали:
А>>Не могли бы вы привести маленький примерчик, хорошо иллюстрирующий проблемы применения auto_ptr в STL контейнерах?
L>auto_ptr нельзя применять в контейнерах. Используй boost::shared_ptr или напиши свой аналог.
Ну вот я и хочу узнать почему нельзя... Примерчик с проблемкой можешь написать?
Здравствуйте, Аноним, Вы писали:
А>Не могли бы вы привести маленький примерчик, хорошо иллюстрирующий проблемы применения auto_ptr в STL контейнерах?
Проблема — в том, что auto_ptr единолично владеет объектом, на который указывает.
Поэтому при копировании/присваивании получается, что несколько auto_ptr'ов указывают (и, следовательно, монопольно владеют) одним объектом.
Когда auto_ptr освобождается (в деструкторе или при изменении), он уничтожает объект. Все остальные указатели получают дохлую ссылку.
Здравствуйте, Аноним, Вы писали:
А>Ну вот я и хочу узнать почему нельзя...
например при сортировке вектора алгоритмом sort может быть такое — опорный элемент копируется во временную переменную, в нем остается NULL, а временная переменная уничтожается при выходе из области видимости. После сортировки имеем часть элементов вектора == NULL.
А>Примерчик с проблемкой можешь написать?
Здравствуйте, <Аноним>, Вы писали:
А>Ну вот я и хочу узнать почему нельзя... Примерчик с проблемкой можешь написать?
Согласно стандарту vector<auto_ptr<хоть что> > не должен даже компилироваться. А проблема в том, что STL полагается на то, что члены контейнеров реализуют присваивание без побочных эффектов.
Здравствуйте, Кодт, Вы писали:
К>Проблема — в том, что auto_ptr единолично владеет объектом, на который указывает.
А зачем там флажок bool _Owns ?
К>Поэтому при копировании/присваивании получается, что несколько auto_ptr'ов указывают (и, следовательно, монопольно владеют) одним объектом.
Они флажок переключают и объектом всегда только один владеет.
К>Когда auto_ptr освобождается (в деструкторе или при изменении), он уничтожает объект. Все остальные указатели получают дохлую ссылку.
Здравствуйте, UgN, Вы писали:
К>>Проблема — в том, что auto_ptr единолично владеет объектом, на который указывает.
UgN>А зачем там флажок bool _Owns ?
Он используется при copy-конструировании auto_ptr, чтобы при передаче auto_ptr внуть функции он не порушил объект на выходе из нее.
К>>Поэтому при копировании/присваивании получается, что несколько auto_ptr'ов указывают (и, следовательно, монопольно владеют) одним объектом.
UgN>Они флажок переключают и объектом всегда только один владеет.
Это ничем не спасает в случае с stl-контейнерами, т.к. там после копирования разрушается не копия, а исходный указатель, который является оунером, и спокойно рушит объект.
ПК>Данный пример не должен компилироваться соответствующим стандарту компилятором.
А если будет обернут, то откомпилируется. (Если в вектор положить класс производный от auto_ptr)
Правильно ли я понимаю, что основная проблема, как указал m.a.g., в том, что
STL полагается на то, что члены контейнеров реализуют присваивание без побочных эффектов
Здравствуйте, Аноним, Вы писали:
ПК>>Данный пример не должен компилироваться соответствующим стандарту компилятором.
А>А если будет обернут, то откомпилируется. (Если в вектор положить класс производный от auto_ptr)
Интересно, как будет реализован копирующий конструктор этого класса, уж не с const_cast? Необходимость подобных танцев с бубном не наводит на размышления? Если ты все же добъешься того, что модифицированный пример будет компилироваться, попробуй добавить в контейнер несколько элементов и отсортировать его...
А>Правильно ли я понимаю, что основная проблема, как указал m.a.g., в том, что STL полагается на то, что члены контейнеров реализуют присваивание без побочных эффектов?
Формально, элементы стандартных контейнеров должны быть CopyConstructible и Assignable. std::auto_ptr не удовлетворяет этим требованиям.
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, Аноним, Вы писали:
А>>Не могли бы вы привести маленький примерчик, хорошо иллюстрирующий проблемы применения auto_ptr в STL контейнерах?
К>Проблема — в том, что auto_ptr единолично владеет объектом, на который указывает. К>Поэтому при копировании/присваивании получается, что несколько auto_ptr'ов указывают (и, следовательно, монопольно владеют) одним объектом. К>Когда auto_ptr освобождается (в деструкторе или при изменении), он уничтожает объект. Все остальные указатели получают дохлую ссылку.
Все это враки! Владеет только один, поэтому в конструкторе копирования для auto_ptr, параметер, переданный в конструктор, на самом деле модифицируется. Его указатель на "владеемый" элемент обнуляется.
Здравствуйте, UgN, Вы писали:
UgN>Здравствуйте, Кодт, Вы писали:
К>>Проблема — в том, что auto_ptr единолично владеет объектом, на который указывает.
UgN>А зачем там флажок bool _Owns ?
Нет там никакого флажка. Флажок ты увидел в реализации STL идущей с MSVC++ 6. Эта реализация 'auto_ptr' давно устарела и имеет мало общего с настоящей реализацией 'auto_ptr'. В правильной релизации 'auto_ptr' никакого флажка не нужно.
Здравствуйте, Аноним, Вы писали:
L>>auto_ptr нельзя применять в контейнерах. Используй boost::shared_ptr или напиши свой аналог.
А>Ну вот я и хочу узнать почему нельзя... Примерчик с проблемкой можешь написать?
Не нужен никако примерчик. Спецификация языка просто напросто открытым текстом запрещает исрользование 'std::auto_ptr' в контейнерах. На основании того, что 'std::auto_ptr' не удовлетворяет стандартным требованиям к элементу контейнера (CopyConstructible и Assignable). Да и не скомпилируется код просто напросто (см. пример в сообщении Павла Кузнецова).
С 'auto_ptr' из комплекта MSVC++ 6 это код скомпилируется. Но этот 'auto_ptr' к настоящему 'std::auto_ptr' почти никакого отношения не имеет.
Здравствуйте, Андрей Тарасевич, Вы писали:
UgN>>А зачем там флажок bool _Owns ?
АТ>Нет там никакого флажка. Флажок ты увидел в реализации STL идущей с MSVC++ 6. Эта реализация 'auto_ptr' давно устарела и имеет мало общего с настоящей реализацией 'auto_ptr'. В правильной релизации 'auto_ptr' никакого флажка не нужно.
Я был просто шокирован, когда не обнаружил у auto_ptr из STL от MSVC++ 6 метода reset().
АТ>>Нет там никакого флажка. Флажок ты увидел в реализации STL идущей с MSVC++ 6. Эта реализация 'auto_ptr' давно устарела и имеет мало общего с настоящей реализацией 'auto_ptr'. В правильной релизации 'auto_ptr' никакого флажка не нужно.
ME>Я был просто шокирован, когда не обнаружил у auto_ptr из STL от MSVC++ 6 метода reset().
появилась необходимость откомпилировать на 6ой студии со стандартной либо и тоже очумел
должно же бить какое то обновление?
Веру-ю-у! В авиацию, в научную революци-ю-у, в механизацию сельского хозяйства, в космос и невесомость! Веру-ю-у! Ибо это объективно-о! (Шукшин)
Здравствуйте, Аноним, Вы писали:
А>Не могли бы вы привести маленький примерчик, хорошо иллюстрирующий проблемы применения auto_ptr в STL контейнерах? А>Спасибо.
std::vector<std::auto_ptr<int> > myVec;
// Здесь что-то вставляем в контейнер
std::sort(myVec.begin(), myVec.end(), some_pred);
// some_pred - некий предикат сравнения для std::auto_ptr<int>
Если скомпилируется, то после выполнения этого кода часть данных в контейнере может быть уничтожена.
Компьютер сделает всё, что вы ему скажете, но это может сильно отличаться от того, что вы имели в виду.
Здравствуйте, Lexey, Вы писали:
L>Здравствуйте, Аноним, Вы писали:
А>>Не могли бы вы привести маленький примерчик, хорошо иллюстрирующий проблемы применения auto_ptr в STL контейнерах?
L>auto_ptr нельзя применять в контейнерах. Используй boost::shared_ptr или напиши свой аналог.
Здравствуйте, dad, Вы писали:
АТ>>>Нет там никакого флажка. Флажок ты увидел в реализации STL идущей с MSVC++ 6. Эта реализация 'auto_ptr' давно устарела и имеет мало общего с настоящей реализацией 'auto_ptr'. В правильной релизации 'auto_ptr' никакого флажка не нужно.
ME>>Я был просто шокирован, когда не обнаружил у auto_ptr из STL от MSVC++ 6 метода reset().
dad>появилась необходимость откомпилировать на 6ой студии со стандартной либо и тоже очумел dad>должно же бить какое то обновление?
d:\pg_files\studio\microsoft_sdk\include\gdiplusflat.h(267) : error C2955: 'iterator' : use of class template requires template argument list
d:\pg_files\studio\vc98\include\stlport\stl\_iterator_base.h(64) : see declaration of 'iterator'
гремучая смесь получатся шестой компилятор , пятый сервис пак, платформ sdk август 2001, stlport 46 ..
Мне приходилось под 6 компилировать уже — там был stlport какой не помню. но все было лучше
Веру-ю-у! В авиацию, в научную революци-ю-у, в механизацию сельского хозяйства, в космос и невесомость! Веру-ю-у! Ибо это объективно-о! (Шукшин)
dad wrote:
> dad>>появилась необходимость откомпилировать на 6ой студии со стандартной либо и тоже очумел > dad>>должно же бить какое то обновление? > > ME>Да — STLPort > > угу > Вот сейчас собираю с stl порт: > > 1) не помешает floor, rand , time .... в std > хотя по исходникам должен бы.. > включаю <cmath> все как положено.
#define _STLP_DO_IMPORT_CSTD_FUNCTIONS
> 2) использую gdiplus еще: > при компиляции такого: > > GpStatus WINGDIPAPI > GdipCreatePathIter(GpPathIterator **iterator, GpPath* path); > > говорит: > > d:\pg_files\studio\microsoft_sdk\include\gdiplusflat.h(267) : error C2955: 'iterator' : use of class template requires template argument list > d:\pg_files\studio\vc98\include\stlport\stl\_iterator_base.h(64) : see declaration of 'iterator'
Странно.. А не стоит ли using namespace std перед включением gdiplus headerов?
>> 1) не помешает floor, rand , time .... в std >> хотя по исходникам должен бы.. >> включаю <cmath> все как положено.
ME>
ME>#define _STLP_DO_IMPORT_CSTD_FUNCTIONS
ME>
в доке ничего нет на этот макрос, я его нашел в _config.h
определил. — не момогает, сейчас попробую поковырять.
Год назад этот проект собирался под 7 без шороха с отключенными расширениями языка.
со стандартной либо правда.
>> 2) использую gdiplus еще: >> при компиляции такого: >> >> GpStatus WINGDIPAPI >> GdipCreatePathIter(GpPathIterator **iterator, GpPath* path);
ME>Странно.. А не стоит ли using namespace std перед включением gdiplus headerов?
Ты прав — стояло — в хидере где использую си функции (п 1) из-за того что не собиралость
std::floor .... пришлось написать floor ну и для порядку временно сделал using
хотя все равно не понятно почему так глючит.
Веру-ю-у! В авиацию, в научную революци-ю-у, в механизацию сельского хозяйства, в космос и невесомость! Веру-ю-у! Ибо это объективно-о! (Шукшин)
dad>в доке ничего нет на этот макрос, я его нашел в _config.h dad>определил. — не момогает, сейчас попробую поковырять. dad>Год назад этот проект собирался под 7 без шороха с отключенными расширениями языка. dad>со стандартной либо правда.
И не поможет.
dad>хотя все равно не понятно почему так глючит.
Проблемы у vc6:
стандартные ф-ии определены в глобальном пространстве имен
через коленку поддерживается using directive
другая проблема:
error C2039: 'vsnprintf' : is not a member of '`global namespace''
--
# if (defined (__MWERKS__) || defined (_STLP_MSVC) || defined (__ICL) || \
( defined (__BORLANDC__) && __BORLANDC__ > 0x530))
using _STLP_VENDOR_CSTD::vsnprintf;
# endif
# endif /* _STLP_NO_CSTD_FUNCTION_IMPORTS */
там же определяет:
# if defined (_STLP_MSVC) || defined (__ICL)
namespace _STLP_VENDOR_CSTD {
inline
int vsnprintf(char *s1, size_t n, const char *s2, va_list v)
{
return ::_vsnprintf(s1, n, s2, v);
}
}
# endif
становится непонятным — по логике макросов я посмотрел:
_STLP_VENDOR_CSTD — пустое — т.е рон вроде как опреляет анонимный нэймспейс,
туда помещает эту функцию и потом ее ипортирует в std..
не пашет!
Веру-ю-у! В авиацию, в научную революци-ю-у, в механизацию сельского хозяйства, в космос и невесомость! Веру-ю-у! Ибо это объективно-о! (Шукшин)
J>>>Никогда не варите яйцо в микроволновке V>>Более того. Даже вареное яйцо нельзя греть в микроволновке. Я проверял.
J>Никогда не вредно вымыть микроволновку
некотоые, на заре, проверяли можно ли сушить в духовке кошек или голову ..
(судя по прессе)
Веру-ю-у! В авиацию, в научную революци-ю-у, в механизацию сельского хозяйства, в космос и невесомость! Веру-ю-у! Ибо это объективно-о! (Шукшин)
Re[3]: auto_ptr и контейнеры
От:
Аноним
Дата:
08.04.04 16:56
Оценка:
А>Ну вот я и хочу узнать почему нельзя... Примерчик с проблемкой можешь написать?
Короче, допустим, ты сделал контейнер автоптров и, допустим, всё скомпилилось.
Допустим ты их туда наложил.
Если какая-то функция контейнера вернёт его тебе по значению (не по ссылке!), в контейнере останется NULL.
dad wrote:
> компилятор 6 (6.00.8804.0) я так понимаю 1200 в их нотации > полную версию не могу чета посомтреть (не знаю где) > > stlport — STLport 4.6.0
Тот код компилится.
А вот с vsnprintf действительно херня какая-то — ф-ция объявляется в анонимном namespace.
ME>Тот код компилится.
да я же написал все ок. а больше я ничего не использую из сишных функций.
ME>А вот с vsnprintf действительно херня какая-то — ф-ция объявляется в анонимном namespace.
угу.
Веру-ю-у! В авиацию, в научную революци-ю-у, в механизацию сельского хозяйства, в космос и невесомость! Веру-ю-у! Ибо это объективно-о! (Шукшин)
d:\pg_files\studio\vc98\include\stlport\cstdio(117) : error C2039: 'vsnprintf' : is not a member of '`global namespace''
d:\pg_files\studio\vc98\include\stlport\cstdio(117) : error C2873: 'vsnprintf' : symbol cannot be used in a using-declaration
ok
Error executing cl.exe.
_>тоже вызывает проблемы, хотя и не должон вроде
у меня другая проблема — я писал, что
функции (при текущем стечении макросов) vsnprintf
определяются в cstdio
# if defined (_STLP_MSVC) || defined (__ICL)
namespace _STLP_VENDOR_CSTD {
inline
int vsnprintf(char *s1, size_t n, const char *s2, va_list v)
{
return ::_vsnprintf(s1, n, s2, v);
}
#pragma message("near")
}
# endif
near
d:\pg_files\studio\vc98\include\stlport\cstdio(119) : error C2039: 'vsnprintf' : is not a member of '`global namespace''
d:\pg_files\studio\vc98\include\stlport\cstdio(119) : error C2873: 'vsnprintf' : symbol cannot be used in a using-declaration
ok
а вызываются как:
using _STLP_VENDOR_CSTD::vsnprintf;
т.е. из глобального namespace..
вот ситуация в ростом виде:
#include <iostream>
namespace
{
void ok()
{
std::cout << "ok" << std::endl;
}
}
namespace my
{
using ::ok;
}
int main()
{
return 0;
};
d:\project\misc\test_any\vc6\stl_port.cpp(14) : error C2039: 'ok' : is not a member of '`global namespace''
d:\project\misc\test_any\vc6\stl_port.cpp(14) : error C2873: 'ok' : symbol cannot be used in a using-declaration
Вопрос:
1) Чей баг — stlport или vc60 ?
2) как побороть?
Веру-ю-у! В авиацию, в научную революци-ю-у, в механизацию сельского хозяйства, в космос и невесомость! Веру-ю-у! Ибо это объективно-о! (Шукшин)
> d:\project\misc\test_any\vc6\stl_port.cpp(14) : error C2039: 'ok' : is not a member of '`global namespace''
> d:\project\misc\test_any\vc6\stl_port.cpp(14) : error C2873: 'ok' : symbol cannot be used in a using-declaration
>
> Вопрос: > 1) Чей баг — stlport или vc60 ? > 2) как побороть?
Здравствуйте, dad, Вы писали:
_>>как dad>Именно этим макросом:
Хм... ясенно.
dad>1) Чей баг — stlport или vc60 ?
Похоже что это баг vc6
В предыдущем посте, я привёл примеры, когда его плющит... Хотя они спокойно воспринимаются g++ (3.2) И вроде вполне соответствуют стандарту...
dad>2) как побороть?