我处于一种相当特殊的情况,需要我使用原始指针 vector 作为类成员:
- 我需要保留一个抽象对象列表 ( I understood I could not use
vector<AbstractClass>
directly )。 - 我无法使用 Boost 或 std::tr1,因此没有智能指针库(因为我所使用的硬件的限制)。
这是我需要的基本示例:
#include <vector>
class Foo
{
virtual void foo() {}
};
class Bar : public Foo
{
void foo(){}
};
class FooBar
{
vector<Foo*> list;
void add(){ list.push_back(new Bar()); }
};
来自Java,我非常害怕指针和内存泄漏。 This post最初建议当对象超出范围时手动删除对象。在 FooBar
的析构函数中执行此操作是否足够?
class FooBar
{
vector<Foo*> list;
void add(){ list.push_back(new Bar()); }
~FooBar(){
for(vector<Foo*>::iterator it=list.begin(); it!=list.end(); it++)
delete *it;
}
};
由 rule of three ,我想我还必须实现一个复制构造函数和一个赋值运算符。以下内容(基于 this 和 that 帖子)是正确的实现吗?
FooBar::FooBar(const FooBar& orig) : list(orig.list.size()) {
try {
vector<Foo*>::iterator thisit = list.begin();
vector<Foo*>::const_iterator thatit = orig.list.cbegin();
for (; thatit != orig.list.cend(); ++thisit, ++thatit)
*thisit = *thatit; // I'm okay with a shallow copy
} catch (...) {
for (vector<Foo*>::iterator i = list.begin(); i != list.end(); ++i)
if (!*i)
break;
else
delete *i;
throw;
}
}
FooBar& operator=(const FooBar& orig){
FooBar tmp(orig);
swap(tmp);
return *this;
}
最佳答案
据我所知,您的代码存在一些重大缺陷。首先,您的第一个代码是正确的,是的,只要您的类拥有对象并且不被复制,您的析构函数就会执行它应该执行的操作。
此外,您的复制构造函数和赋值运算符看起来有问题。首先,如果您可以接受浅复制,那么您甚至不必编写函数,std::vector
的复制构造函数和赋值运算符无论如何都会完成您手动完成的操作。我认为你不需要那个 try-catch block 。顺便问一下,赋值运算符中的交换
的实现在哪里?
为了您的目的,一个非常小的引用计数方案就可以工作:
class FooPtr
{
Foo* _raw;
size_t* _ctl;
FooPtr(Foo* ptr) :
_raw(ptr), _ctl(new size_t(0))
{
}
template <class T>
FooPtr(T* ptr) : FooPtr(static_cast<Foo*>(ptr)) {}
FooPtr(const FooPtr& rhs) :
_raw(rhs._raw), _ctl(rhs._ctl)
{
++(*_ctl);
}
~FooPtr()
{
if (_raw == nullptr) return;
--(*_ctl);
if (*_ctl == 0)
{
delete _raw;
delete _ctl;
}
}
FooPtr& operator=(FooPtr ptr)
{
std::swap(*this, ptr);
return *this;
}
Foo* operator->()
{
return _raw;
}
Foo& operator*()
{
return *_raw;
}
}
你的类现在看起来像这样,不需要析构函数、复制构造函数或赋值运算符:
class FooBar
{
vector<FooPtr> list;
void add(){ list.emplace_back(new Bar()); }
}
我写得很快,它可能包含错误,尽管它为您提供了我认为的基本想法。另外,我还使用了一些 C++11 功能,例如 emplace_back
和 nullptr
,但它们可以轻松地转换为非 11 代码。
关于c++ - 作为类成员管理指针 vector ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35937148/