Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/129.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 分配给已删除/未初始化的对象_C++_C++11_Initialization_Destructor_Unions - Fatal编程技术网

C++ 分配给已删除/未初始化的对象

C++ 分配给已删除/未初始化的对象,c++,c++11,initialization,destructor,unions,C++,C++11,Initialization,Destructor,Unions,我有一节这样的课 struct foo { bool type; union { struct { std::string s; }; struct { std::function<std::string(void)> f; }; }; }; structfoo{ 布尔型; 联合{ 结构{std::string s;}; 结构{std::function f;}; }; }; 我需要定义赋值运算符,但当我赋值不同的类型时,我

我有一节这样的课

struct foo {
    bool type;
    union {
        struct { std::string s; };
        struct { std::function<std::string(void)> f; };
    };
};
structfoo{
布尔型;
联合{
结构{std::string s;};
结构{std::function f;};
};
};
我需要定义赋值运算符,但当我赋值不同的类型时,我基本上是赋值给未初始化的字段(我知道我必须先显式调用析构函数)

我猜这样的赋值是未定义的行为,因为我不知道字符串或函数的赋值是否不重用某些字段

如何在不调用任何未定义行为的情况下正确执行此操作


我仅限于C++ 11。< /P> < P>第一,C++中的匿名结构不好。例如,您可以使用:

union {
    std::string s;
    std::function<std::string(void)> f;
};
联合{
std::字符串s;
std::函数f;
};
我的猜测是,这种分配是未定义的行为

如何在不调用任何未定义行为的情况下正确执行此操作

可以使用标记的联合模式。您似乎已经有了
类型
成员。您可以使用它来指定哪个成员处于活动状态。如果您对该成员有其他计划,只需添加一个新计划即可

一旦可以使用结构成员检查哪个联合成员处于活动状态,就可以销毁活动成员,然后复制并构造以前的非活动联合成员,最后更新
type
以表示新的活动成员



也就是说,您可以通过使用标记的联合的预先存在的通用实现来节省一些时间。其中有一个例子,

首先,C++中的匿名结构不好。例如,您可以使用:

union {
    std::string s;
    std::function<std::string(void)> f;
};
联合{
std::字符串s;
std::函数f;
};
我的猜测是,这种分配是未定义的行为

如何在不调用任何未定义行为的情况下正确执行此操作

可以使用标记的联合模式。您似乎已经有了
类型
成员。您可以使用它来指定哪个成员处于活动状态。如果您对该成员有其他计划,只需添加一个新计划即可

一旦可以使用结构成员检查哪个联合成员处于活动状态,就可以销毁活动成员,然后复制并构造以前的非活动联合成员,最后更新
type
以表示新的活动成员


也就是说,您可以通过使用标记的联合的预先存在的通用实现来节省一些时间。举个例子,有一个

我猜这样的赋值是未定义的行为,因为我不知道字符串或函数的赋值是否不重用某些字段

猜对了!赋值的前提条件始终是左侧实际上是该类型的对象。如果左手边没有物体,所有的赌注都没有了

如何在不调用任何未定义行为的情况下正确执行此操作

建筑!当您没有对象时,获取对象的唯一方法是创建它。因为我们想在一个特定的位置创建它,这是新的

我不知道为什么要将类型包装在一个额外的结构中,您想这样做:

union U {
    U() { }
    ~U() { }

    std::string s;
    std::function<std::string(void)> f;
} u;
union U{
U(){}
~U(){}
std::字符串s;
std::函数f;
}u;
这样,您的赋值运算符将是:

foo& operator=(foo const& rhs) {
    if (type) {
        if (rhs.type) {
            u.s = rhs.u.s;
        } else {
            u.s.~string();
            new (&u.f) std::function<std::string(void)>(rhs.u.f);
        }
    } else {
        if (!rhs.type) {
            u.f = rhs.u.f;
        } else {
            u.f.~function();
            new (&u.s) std::string(rhs.u.s);
        }
    }

    return *this;
}
foo&operator=(foo const&rhs){
如果(类型){
if(rhs类型){
u、 s=rhs.u.s;
}否则{
u、 s.~string();
新(&u.f)标准::功能(rhs.u.f);
}
}否则{
如果(!rhs.type){
u、 f=右S.u.f;
}否则{
u、 f.~函数();
新(&u.s)标准::字符串(rhs.u.s);
}
}
归还*这个;
}
您可能希望重构其中的一些,以支持移动分配,而不需要大量重复,但这只是一个粗略的想法

我猜这样的赋值是未定义的行为,因为我不知道字符串或函数的赋值是否不重用某些字段

猜对了!赋值的前提条件始终是左侧实际上是该类型的对象。如果左手边没有物体,所有的赌注都没有了

如何在不调用任何未定义行为的情况下正确执行此操作

建筑!当您没有对象时,获取对象的唯一方法是创建它。因为我们想在一个特定的位置创建它,这是新的

我不知道为什么要将类型包装在一个额外的结构中,您想这样做:

union U {
    U() { }
    ~U() { }

    std::string s;
    std::function<std::string(void)> f;
} u;
union U{
U(){}
~U(){}
std::字符串s;
std::函数f;
}u;
这样,您的赋值运算符将是:

foo& operator=(foo const& rhs) {
    if (type) {
        if (rhs.type) {
            u.s = rhs.u.s;
        } else {
            u.s.~string();
            new (&u.f) std::function<std::string(void)>(rhs.u.f);
        }
    } else {
        if (!rhs.type) {
            u.f = rhs.u.f;
        } else {
            u.f.~function();
            new (&u.s) std::string(rhs.u.s);
        }
    }

    return *this;
}
foo&operator=(foo const&rhs){
如果(类型){
if(rhs类型){
u、 s=rhs.u.s;
}否则{
u、 s.~string();
新(&u.f)标准::功能(rhs.u.f);
}
}否则{
如果(!rhs.type){
u、 f=右S.u.f;
}否则{
u、 f.~函数();
新(&u.s)标准::字符串(rhs.u.s);
}
}
归还*这个;
}

您可能希望重构其中的一些,以支持移动分配,而不需要大量重复,但这只是一个粗略的想法

C++11非常友好,甚至不允许这样做。由于联合包含具有非平凡构造函数和析构函数的字段,
struct foo
已隐式删除默认构造函数和析构函数

我的老版本3.4.1(带有选项std=c++11)在尝试创建
struct foo
时阻塞了:

error: call to implicitly-deleted 

如果我尝试手动初始化
struct foo
(我稍微更改了
foo
,以避免匿名字段):


C++11非常友好,甚至不允许这样做。由于联合包含具有非平凡构造函数和析构函数的字段,
struct foo
已隐式删除默认构造函数和析构函数

我的老版本3.4.1(带有选项std=c++11)在我尝试运行时阻塞了
note: destructor of 'foo' is implicitly deleted because variant field 's' has a non-trivial destructor
        struct { std::string s; } s;
                                  ^