ШАГ 1 Давайте решим эту проблему прямым путем:
#include <iostream>
#include <vector>
#include <algorithm>
template<> struct std::less<std::auto_ptr<int>>: public std::binary_function<std::auto_ptr<int>, std::auto_ptr<int>, bool> {
bool operator()(const std::auto_ptr<int>& _Left, const std::auto_ptr<int>& _Right) const
{ // apply operator< to operands
return *_Left < *_Right;
}
};
int wmain() {
using namespace std;
auto_ptr<int> apai(new int(1)), apai2(new int(2)), apai3(new int(3));
vector<auto_ptr<int>> vec;
vec.push_back(apai3);
vec.push_back(apai);
vec.push_back(apai2);
for ( vector<auto_ptr<int>>::const_iterator i(vec.cbegin()) ; i != vec.cend() ; ++i )
wcout << i->get() << L'\t';
vector<int> vec2;
vec2.push_back(3);
vec2.push_back(2);
vec2.push_back(5);
sort(vec2.begin(), vec2.end(), less<int>());
sort(vec.begin(), vec.end(), less<auto_ptr<int>>());
return 0;
}
На MSVCPP11 текст ошибки следующий: _ Ошибка 1 ошибка C2558:класс 'std :: auto _ptr <<em> Ty>': конструктор копирования недоступен или конструктор копирования объявлен как «явный» c: \ program files (x86) \ microsoft visual studio 11.0 \ vc \ include \ xmemory0 608
Вывод таков: я даже не могу скомпилировать такой пример.Почему они мешают мне делать то, что я не могу скомпилировать?Их предупреждения не всегда верны.
ШАГ 2
Мы не можем использовать auto_ptr
в качестве vector
типа элемента напрямую из-за дизайна auto_ptr
.Но мы можем обернуть `auto_ptr 'способом, представленным ниже.
#include <iostream>
#include <vector>
#include <algorithm>
template<typename T> class auto_ptr_my: public std::auto_ptr<T> {
public:
explicit auto_ptr_my(T *ptr = 0) {
this->reset(ptr);
}
auto_ptr_my<T> &operator=(const auto_ptr_my<T> &right) {
*(static_cast<auto_ptr<T> *>(this)) = *(static_cast<auto_ptr<T> *>(const_cast<auto_ptr_my *>(&right)));
return *this;
}
auto_ptr_my(const auto_ptr_my<T>& right) {
*this = right;
}
};
template<> struct std::less<auto_ptr_my<int>>: public std::binary_function<auto_ptr_my<int>, auto_ptr_my<int>, bool> {
bool operator()(const auto_ptr_my<int>& _Left, const auto_ptr_my<int>& _Right) const
{ // apply operator< to operands
return *_Left < *_Right;
}
};
int wmain() {
using namespace std;
auto_ptr_my<int> apai(new int(1)), apai2(new int(2)), apai3(new int(3));
vector<auto_ptr_my<int>> vec;
vec.push_back(apai3);
vec.push_back(apai);
vec.push_back(apai2);
for ( vector<auto_ptr_my<int>>::const_iterator i(vec.cbegin()) ; i != vec.cend() ; ++i )
wcout << **i << L'\t';
sort(vec.begin(), vec.end(), less<auto_ptr_my<int>>());
for ( vector<auto_ptr_my<int>>::const_iterator i(vec.cbegin()) ; i != vec.cend() ; ++i )
wcout << **i << L'\t';
return 0;
}
Этот код хорошо работает, показывая, что auto_ptr
можно использовать с vector
и sort
без утечек памяти исбои .
ШАГ 3 Как указано в KennyTM ниже:
добавьте этот код перед return 0;
оператором:
std::vector<auto_ptr_my<int>> vec2 = vec;
for ( vector<auto_ptr_my<int>>::const_iterator i(vec2.cbegin()) ; i != vec2.cend() ; ++i )
wcout << **i << L'\t';
wcout << std::endl;
for ( vector<auto_ptr_my<int>>::const_iterator i(vec.cbegin()) ; i != vec.cend() ; ++i )
wcout << **i << L'\t';
wcout << std::endl;
... и получить утечки памяти!
ЗАКЛЮЧЕНИЕ Иногда мы можем использовать auto_ptr
с контейнерами без видимых сбоев ,иногда нет.Во всяком случае, это плохая практика.Но не забывайте, что auto_ptr
спроектирован таким образом, что вы не можете использовать его прямо с контейнерами и алгоритмами STL: вам придется написать некоторый код-обертку.Наконец, использование auto_ptr
с контейнерами STL - на ваш страх и риск.Например, некоторые реализации sort
не приведут к сбою при обработке элементов vector
, но другие реализации приведут непосредственно к сбою.
Этот вопрос имеет академические цели.Спасибо KennyTM за предоставленный пример аварии STEP 3!