似乎每次我向向量m_test添加一个对象时,都会调用析构函数方法.我错过了什么吗?我怎样才能防止这种情况发生?
class TEST
{
public:
TEST();
~TEST();
int * x;
};
TEST::TEST()
{
}
TEST::~TEST()
{
... it is called every time I push_back something to the vector ...
delete x;
}
vector<TEST> m_test;
for (unsigned int i=0; i<5; i++)
{
m_test.push_back(TEST());
}
Run Code Online (Sandbox Code Playgroud)
Ant*_*lov 12
这里的问题是你违反了三条规则.你的类有一个析构函数,所以你也需要一个复制构造函数和赋值运算符.或者,您不能允许复制您的类(例如,通过制作T(T const&)和T& operator=(T const&)私有,或通过派生boost::noncopyable),然后调整向量的大小而不是使用push_back.
在第一种情况下,您可以像往常一样push_back选择自己的课程.在第二个,语法将是类似的
std::vector<TEST> vec(5);
// vec now has five default-constructed elements of type TEST.
Run Code Online (Sandbox Code Playgroud)
不做这两件事都是一个坏主意,因为你很可能在某些时候遇到双重删除问题 - 即使你认为你永远不会复制或分配一个TEST地方x != nullptr,明确禁止它会更安全.
顺便说一句,如果你有需要删除的成员指针当对象超出范围时,可以考虑使用智能指针像scoped_ptr,unique_ptr以及shared_ptr(也许auto_ptr如果您无法使用升压或C++ 11).
当你push_back被临时摧毁时,它就不会被调用.
要在您的示例中修复它:
TEST test;
for (int i = 0; i < 5; ++i)
{
m_test.push_back(test);
}
Run Code Online (Sandbox Code Playgroud)
应该只调用一次.
你的代码TEST在循环中创建一个临时的,使用它push_back,然后当循环结束/重复并被销毁时,临时超出范围.这恰好发生了,因为临时TEST需求得到了清理.
如果你想避免这种情况,你需要做其他事情,但每次推送都要做一个临时对象.一个可能的解决方案是:
vector<TEST> m_test(5); // Note reserving space in the vector for 5 objects
std::fill(m_test.begin(), m_test.end(), TEST()); // Fill the vector with the default ctor
Run Code Online (Sandbox Code Playgroud)
根据STL的优化方式,这可能不需要进行多次复制.
如果在TEST类中实现复制构造函数,您也可以获得更好的处理,例如:
TEST::TEST(const TEST & other)
{
x = new int(*other.x); // Not entirely safe, but the simplest copy ctor for this example.
}
Run Code Online (Sandbox Code Playgroud)
这是否合适,或者你如何处理它,取决于你的类及其需求,但是当你定义了自己的常规构造函数和析构函数时,通常应该有一个复制构造函数(否则编译器会生成一个,在这种情况下,它将导致复制和挂起指针x).