auto_ptr说明:
C++的auto_ptr所做的事情,就是动态分配对象以及当对象不再需要时自动执行清理。
使用std::auto_ptr,要#include <memory>。
auto_ptr作用:
c++中可以通过auto_ptr实现对内存的管理,当auto_ptr绑定指针后,在auto_ptr结束的时候释放地址所指向的内存
关于STL中使用auto_ptr的问题:
我们通过一段代码来观察:
#include <memory>
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<auto_ptr<int>> v(10);
for(int i=0;i<10;i++)
{
v[i] = auto_ptr<int>(new int(1));
}
for(int i=0;i<10;i++)
{
cout<<*v[i]<<endl;
}
return 0;
}
查看网上说auto_ptr不能再stl中使用,但是在vs2017编写代码并编译运行是没有问题的,所以又在网上查找发现不能运行的挺多的,后来在linux下编译运行:
g++ auto_ptr.cpp
发现编译不能通过
auto_ptr.cpp: In function ‘int main()’:
auto_ptr.cpp:9:24: error: ‘>>’ should be ‘> >’ within a nested template argument list
vector<auto_ptr<int>> v(10);
^
In file included from /usr/include/c++/5/memory:64:0,
from auto_ptr.cpp:1:
/usr/include/c++/5/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, const _T2&) [with _T1 = std::auto_ptr<int>; _T2 = std::auto_ptr<int>]’:
/usr/include/c++/5/bits/stl_uninitialized.h:202:18: required from ‘static _ForwardIterator std::__uninitialized_fill_n<_TrivialValueType>::__uninit_fill_n(_ForwardIterator, _Size, const _Tp&) [with _ForwardIterator = std::auto_ptr<int>*; _Size = long unsigned int; _Tp = std::auto_ptr<int>; bool _TrivialValueType = false]’
/usr/include/c++/5/bits/stl_uninitialized.h:247:17: required from ‘_ForwardIterator std::uninitialized_fill_n(_ForwardIterator, _Size, const _Tp&) [with _ForwardIterator = std::auto_ptr<int>*; _Size = long unsigned int; _Tp = std::auto_ptr<int>]’
/usr/include/c++/5/bits/stl_uninitialized.h:358:39: required from ‘_ForwardIterator std::__uninitialized_fill_n_a(_ForwardIterator, _Size, const _Tp&, std::allocator<_Tp2>&) [with _ForwardIterator = std::auto_ptr<int>*; _Size = long unsigned int; _Tp = std::auto_ptr<int>; _Tp2 = std::auto_ptr<int>]’
/usr/include/c++/5/bits/stl_vector.h:1301:33: required from ‘void std::vector<_Tp, _Alloc>::_M_fill_initialize(std::vector<_Tp, _Alloc>::size_type, const value_type&) [with _Tp = std::auto_ptr<int>; _Alloc = std::allocator<std::auto_ptr<int> >; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::value_type = std::auto_ptr<int>]’
/usr/include/c++/5/bits/stl_vector.h:306:27: required from ‘std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>::size_type, const value_type&, const allocator_type&) [with _Tp = std::auto_ptr<int>; _Alloc = std::allocator<std::auto_ptr<int> >; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::value_type = std::auto_ptr<int>; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<std::auto_ptr<int> >]’
auto_ptr.cpp:9:31: required from here
/usr/include/c++/5/bits/stl_construct.h:83:7: error: no matching function for call to ‘std::auto_ptr<int>::auto_ptr(const std::auto_ptr<int>&)’
::new(static_cast<void*>(__p)) _T1(__value);
^
In file included from /usr/include/c++/5/memory:88:0,
from auto_ptr.cpp:1:
/usr/include/c++/5/backward/auto_ptr.h:260:7: note: candidate: std::auto_ptr<_Tp>::auto_ptr(std::auto_ptr_ref<_Tp>) [with _Tp = int]
auto_ptr(auto_ptr_ref<element_type> __ref) throw()
^
/usr/include/c++/5/backward/auto_ptr.h:260:7: note: no known conversion for argument 1 from ‘const std::auto_ptr<int>’ to ‘std::auto_ptr_ref<int>’
/usr/include/c++/5/backward/auto_ptr.h:125:9: note: candidate: template<class _Tp1> std::auto_ptr<_Tp>::auto_ptr(std::auto_ptr<_Tp1>&)
auto_ptr(auto_ptr<_Tp1>& __a) throw() : _M_ptr(__a.release()) { }
^
/usr/include/c++/5/backward/auto_ptr.h:125:9: note: template argument deduction/substitution failed:
In file included from /usr/include/c++/5/memory:64:0,
from auto_ptr.cpp:1:
/usr/include/c++/5/bits/stl_construct.h:83:7: note: types ‘std::auto_ptr<_Tp1>’ and ‘const std::auto_ptr<int>’ have incompatible cv-qualifiers
::new(static_cast<void*>(__p)) _T1(__value);
^
In file included from /usr/include/c++/5/memory:88:0,
from auto_ptr.cpp:1:
/usr/include/c++/5/backward/auto_ptr.h:112:7: note: candidate: std::auto_ptr<_Tp>::auto_ptr(std::auto_ptr<_Tp>&) [with _Tp = int] <near match>
auto_ptr(auto_ptr& __a) throw() : _M_ptr(__a.release()) { }
^
/usr/include/c++/5/backward/auto_ptr.h:112:7: note: conversion of argument 1 would be ill-formed:
In file included from /usr/include/c++/5/memory:64:0,
from auto_ptr.cpp:1:
/usr/include/c++/5/bits/stl_construct.h:83:7: error: binding ‘const std::auto_ptr<int>’ to reference of type ‘std::auto_ptr<int>&’ discards qualifiers
::new(static_cast<void*>(__p)) _T1(__value);
^
In file included from /usr/include/c++/5/memory:88:0,
from auto_ptr.cpp:1:
/usr/include/c++/5/backward/auto_ptr.h:103:7: note: candidate: std::auto_ptr<_Tp>::auto_ptr(std::auto_ptr<_Tp>::element_type*) [with _Tp = int; std::auto_ptr<_Tp>::element_type = int]
auto_ptr(element_type* __p = 0) throw() : _M_ptr(__p) { }
^
/usr/include/c++/5/backward/auto_ptr.h:103:7: note: no known conversion for argument 1 from ‘const std::auto_ptr<int>’ to ‘std::auto_ptr<int>::element_type* {aka int*}’
后来想了一下是不是和编译条件有关系,添加 -std=c++11编译通过:
g++ auto_ptr.cpp -std=c++11
执行:
./a.out
结果:
1
1
1
1
1
1
1
1
1
1
通过测试我们可以发现其实只要指定编译是用c++11标准编译就可以通过,说明auto_ptr在c++11和之前的实现是不一样的。
c++标准规定STL元素必须是“可复制构造的”和“可分配的”。换句话说,必须能够分配或复制一个元素,并且这两个元素在逻辑上是独立的。C++11之前的std: auto_ptr 得实现是不满足此要求。但是auto_ptr是不支持多个auto_ptr指向同一块内存的,所以在执行=和copy操作时会把原先的auto_ptr指向空。
然而STL容器在分配内存的时候,必须要能够拷贝构造容器的元素。而且拷贝构造的时候,不能修改原来元素的值。而auto_ptr在拷贝构造的时候,一定会修改元素的值。所以STL元素不能使用auto_ptr。
所以我们可以大胆的猜测c++11中对auto_ptr的拷贝和=重载做了不同的实现,目前博主还不是太清楚。