我使用的是boost- variant,当在variant中切换类型时,我希望确保析构函数被调用。下面的代码“工作”,但我不确定为什么。我觉得它应该分段错误,因为它在一个未初始化的指针上调用一个delete。幕后是不是有一些助推变种的魔法在发生?
#include <iostream>
#include <boost/variant.hpp>
using namespace std;
class A
{
public:
A() {}
virtual ~A() { cout << "Destructing A" << endl; }
};
class B
{
public:
B() {}
virtual ~B() { cout << "Destructing B" << endl; }
};
typedef boost::variant<A*, B*> req;
class delete_visitor : public boost::static_visitor<void>
{
public:
inline void operator() (A *a) const
{
cout << "Will destruct A" << endl;
delete a;
}
inline void operator() (B *b) const
{
cout << "Will destruct B" << endl;
delete b;
}
};
class Wrapper
{
public:
Wrapper(int s) {
setBackend(s);
}
virtual ~Wrapper() {
// cleanup
boost::apply_visitor(delete_visitor(), my_pick);
}
void setBackend(int s)
{
// make sure if we already have put something in our variant, we clean it up
boost::apply_visitor(delete_visitor(), my_pick);
if(s == 0)
my_pick = new A();
else
my_pick = new B();
}
private:
req my_pick;
};
int main()
{
Wrapper *w = new Wrapper(0);
w->setBackend(1);
delete w;
return 0;
}以下是我得到的输出结果:
Will destruct A
Will destruct A
Destructing A
Will destruct B
Destructing B发布于 2013-07-15 05:45:23
根据boost::variant的
“永不为空”保证
类型variant的所有实例V都保证V构造了类型Ti之一的内容,即使对V的操作先前已经失败。
查看"boost/variant.hpp",特别是variant的默认构造函数,您会看到:
// boost/variant.hpp: 1383
variant()
{
// NOTE TO USER :
// Compile error from here indicates that the first bound
// type is not default-constructible, and so variant cannot
// support its own default-construction.
//
new( storage_.address() ) internal_T0();
indicate_which(0); // zero is the index of the first bounded type
}对于被绑定的变量类型,第一个类型获取default-init。这意味着对于您的req类型,A *将获得零初始化。这也意味着B *是零初始化的,因为变体可以被视为一个联合。
发布于 2013-07-15 04:09:22
在未初始化的指针上调用delete是未定义的行为。它编译的事实并不意味着代码是合法的。无论如何,我认为你应该对这类事情使用内存管理:
typedef boost::variant<boost::shared_ptr<A>, boost::shared_ptr<B>> req;
// ....
if (s == 0)
my_pick = boost::make_shared<A>();
else
my_pick = boost::make_shared<B>();发布于 2013-07-15 04:14:25
在未初始化的指针上调用delete是未定义的行为,这意味着任何事情都可能发生,包括什么都不发生。
特别是如果未初始化的指针恰好在以前没有使用过的内存中,则该内存不太可能包含零,因此delete将获取一个空指针并不执行任何操作。
第二个可能是(!)结果是,正如您所预期的那样,您得到了一个段错误,因为指针恰好位于不包含有效指针值的内存中。
其他可能是:指针恰好位于包含完全不相关对象的地址的位置,销毁该地址(很可能是在调用完全错误的析构函数时)。或者指针指向堆,但在中间的某个地方,你会破坏内部堆结构,导致很久以后神秘的崩溃。
这份清单绝不是详尽的。
https://stackoverflow.com/questions/17643088
复制相似问题