STEP 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< Ty>': 没有可用的复制构造函数或复制构造函数被声明为“显式” c:\program files (x86)\microsoft visual studio 11.0\vc\include\xmemory0 608
结论是:我什至无法编译这样的例子。为什么他们阻止我做一些我无法编译的事情?他们的预防措施并不总是正确的。
第2步
由于设计原因,我们不能直接auto_ptr
用作元素类型。但是我们可以用下面介绍的方式包装`auto_ptr'。vector
auto_ptr
#include <iostream>
#include <vector>
#include <algorithm>
#include <memory>
#include <functional>
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<std::auto_ptr<T> *>(this)) = *(static_cast<std::auto_ptr<T> *>(const_cast<auto_ptr_my *>(&right)));
return *this;
}
auto_ptr_my(const auto_ptr_my<T>& right) {
*this = right;
}
};
namespace std
{
template<> struct 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
的情况下使用容器,有时则不能。无论如何,这是不好的做法。但是不要忘记,它的设计方式不能直接与 STL 容器和算法一起使用:相反,您必须编写一些包装器代码。最后,使用STL 容器需要您自担风险。例如,某些实现在处理元素时不会导致崩溃,但其他实现会直接导致崩溃。auto_ptr
auto_ptr
sort
vector
这个问题有学术目的。感谢 KennyTM 提供 STEP 3 崩溃示例!