首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在boost-variant中调用匹配类型的析构函数

在boost-variant中调用匹配类型的析构函数
EN

Stack Overflow用户
提问于 2013-07-15 03:50:24
回答 3查看 1K关注 0票数 2

我使用的是boost- variant,当在variant中切换类型时,我希望确保析构函数被调用。下面的代码“工作”,但我不确定为什么。我觉得它应该分段错误,因为它在一个未初始化的指针上调用一个delete。幕后是不是有一些助推变种的魔法在发生?

代码语言:javascript
复制
#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;
}

以下是我得到的输出结果:

代码语言:javascript
复制
Will destruct A
Will destruct A
Destructing A
Will destruct B
Destructing B
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-07-15 05:45:23

根据boost::variant

“永不为空”保证

类型variant的所有实例V都保证V构造了类型Ti之一的内容,即使对V的操作先前已经失败。

查看"boost/variant.hpp",特别是variant的默认构造函数,您会看到:

代码语言:javascript
复制
// 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 *是零初始化的,因为变体可以被视为一个联合。

票数 2
EN

Stack Overflow用户

发布于 2013-07-15 04:09:22

在未初始化的指针上调用delete是未定义的行为。它编译的事实并不意味着代码是合法的。无论如何,我认为你应该对这类事情使用内存管理:

代码语言:javascript
复制
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>();
票数 1
EN

Stack Overflow用户

发布于 2013-07-15 04:14:25

在未初始化的指针上调用delete是未定义的行为,这意味着任何事情都可能发生,包括什么都不发生。

特别是如果未初始化的指针恰好在以前没有使用过的内存中,则该内存不太可能包含零,因此delete将获取一个空指针并不执行任何操作。

第二个可能是(!)结果是,正如您所预期的那样,您得到了一个段错误,因为指针恰好位于不包含有效指针值的内存中。

其他可能是:指针恰好位于包含完全不相关对象的地址的位置,销毁该地址(很可能是在调用完全错误的析构函数时)。或者指针指向堆,但在中间的某个地方,你会破坏内部堆结构,导致很久以后神秘的崩溃。

这份清单绝不是详尽的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17643088

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档