我可以把auto_ptr放在STL容器中吗
Can I get away with putting auto_ptr in a STL container?
我继承了一个接口,并实现了一个虚拟函数,该函数应该对动态分配的对象列表执行一些工作。第一步是根据一些自定义等效标准从列表中删除重复项:
class Foo { /* ... */ };
struct FooLess
{
bool operator()(const Foo *lhs, const Foo *rhs);
}
struct FooEqual
{
bool operator()(const Foo *lhs, const Foo *rhs);
}
void doStuff(std::list<Foo*> &foos)
{
// use the sort + unique idiom to find and erase duplicates
FooLess less;
FooEqual equal;
foos.sort( foos.begin(), foos.end(), less );
foos.erase(
std::unique( foos.begin(), foos.end(), equal ),
foos.end() ); // memory leak!
}
问题是使用sort
+unique
不会清理内存,并且要erase
d的元素在unique
之后有未指定的值,所以我无法在erase
ing之前自己执行清理
void doStuff(std::list<Foo*> &foos)
{
// make a temporary copy of the input as a list of auto_ptr's
std::list<auto_ptr<Foo>> auto_foos;
for (std::list<Foo>::iterator it = foos.begin(); it != foos.end(); ++it)
auto_foos.push_back(auto_ptr<Foo>(*it));
foos.clear();
FooLess less; // would need to change implementation to work on auto_ptr<Foo>
FooEqual equal; // likewise
auto_foos.sort( auto_foos.begin(), auto_foos.end(), less );
auto_foos.erase(
std::unique( auto_foos.begin(), auto_foos.end(), equal ),
auto_foos.end() ); // okay now, duplicates deallocated
// transfer ownership of the remaining objects back
for (std::list<auto_ptr<Foo>>::iterator it = auto_foos.begin();
it != auto_foos.end(); ++it)
{ foos.push_back(it->get()); it->release(); }
}
这样可以吗,还是我错过了什么?
我无法使用C++11(可能会使用Boost)或更改函数签名以接受简单的Foo
s列表。
要将对象放入标准容器中,对象需要值语义(标准中说"copy assignable"answers"copy constructable")。除其他外,这意味着复制构造函数和赋值运算符需要创建对象的副本(保持原始副本不变)
auto_ptr复制构造函数不执行此操作。相反,复制构造函数和赋值运算符会转移指针的所有权。
因此,标准容器不可能包含auto_ptr。
许多实现(如编译器和标准库)都对标准容器和/或auto_ptr进行了编码,因此尝试使用auto_ptr的容器会触发编译器错误。不幸的是,并不是所有的实现都能做到这一点。
在C++98中通常可以使用以下方法:
- 定义一些指针来做
std::auto_ptr
不能做的事情。有一个旧版本的指针,它包含一个类型为bool
的额外字段,标记所有权。它被标记为可变,因此在复制时也可以在要读取的对象中对其进行修改。只有当owned
为true时,对象才会在末尾被删除。类似于:
===
template <class T> class owning_ptr
{
T* ptr;
mutable bool owns;
public:
void operator =(T* src) { ptr = src; owns = true; }
owning_ptr(const owning_ptr& other)
{
// copy the pointer, but STEAL ownership!
ptr = other.ptr; owns = other.owns; other.owns = false;
}
T* release() { owns = false; return ptr; }
~owning_ptr() { if ( owns ) delete ptr; }
/* ... some lacking stuff ..*/
};
您可以试用
boost::shared_ptr
您可以尝试在循环中执行
std::adjacent_find
,而不是std::unique
。然后,您只需找到与equal
"相同"的所有元素。如果有多个元素,您将在适当的位置擦除它们(您可以这样做,因为它是一个列表,所以迭代器仍然有效)。
相关文章:
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 在C应用程序中运行C++(带有STL)函数
- 使用2个键的cpp-stl::优先级队列排序不正确
- 在STL容器中使用模板类
- 尝试将lambda函数放在队列中时出现一般分配器错误(可能是与unique_ptr有关的错误)
- 用C++中的CPerson(类)类型的对象初始化STL矢量
- 将stl字符串缩小到小于15个字符的容量
- 在为LINUX创建共享库时,如何避免STL的私有/弱副本
- 根据用户输入用字母填充矢量,并将"开始"和"结束"放在四肢
- 检查函数返回类型是否与STL容器类型值相同
- STL算法函数在多个一维容器上的使用
- 在STL - C++中按成绩对学生列表进行排序?
- 将非平凡的项目放在多集中
- 为什么 STL 容器适配器堆栈中的 top 返回常量引用?
- λ可以适应STL吗?
- 为什么我不应该把所有东西都放在标题中?
- 为什么使用 NDK 不能存在不同的 stl 实现?
- 如果我真的真的想从 STL 容器继承,并且我继承构造函数并删除新运算符,会发生什么?
- 我可以把auto_ptr放在STL容器中吗