在结构的并集成员中使用std :: string时,不能引用默认构造函数 [英] Default constructor cannot be referenced when using std::string in union member of a struct

查看:46
本文介绍了在结构的并集成员中使用std :: string时,不能引用默认构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个非常基本的结构,具有一个枚举和一个联合.

I have a very basic struct that has an enum and a union.

typedef struct
{
    enum v{a,b,c}v;
    union w{
        int a;
        bool b;
        std::string c;
    }w;

}Data_Set2;

int main()
{
Data_Set2 val; // Shows errror that the default constructor cannot be referenced
return 0;
}

在使用这种结构时,我得到错误代码C2280,该默认代码无法被引用.当我以稍微不同的方式声明struct时,如下所示

On using such a struct I get the Error Code C2280 that the default constructor cannot be referenced. When I declare the struct in a slightly different way as following

typedef struct
{
    enum v{a,b,c}v;
    union w{
        int a;
        bool b;
        std::string c;
    }; // changed here.

}Data_Set2;

该错误不再存在.我不明白这背后的原因.谁能解释为什么会这样

The Error no longer exists. I fail to understand the reason behind this. Could anyone explain why this happens

推荐答案

来自 https://en.cppreference.com/w/cpp/language/union (或参见标准):

如果联合包含具有非平凡特殊成员函数(复制/移动构造函数,复制/移动分配或析构函数)的非静态数据成员,则该函数默认在联合中被删除并且需要定义由程序员明确表示.

If a union contains a non-static data member with a non-trivial special member function (copy/move constructor, copy/move assignment, or destructor), that function is deleted by default in the union and needs to be defined explicitly by the programmer.

如果联合包含具有非平凡默认构造函数的非静态数据成员,则默认情况下将删除联合的默认构造函数,除非联合的变体成员具有默认成员初始值设定项.

If a union contains a non-static data member with a non-trivial default constructor, the default constructor of the union is deleted by default unless a variant member of the union has a default member initializer .

最多一个变体成员可以具有一个默认的成员初始化器.

At most one variant member can have a default member initializer.

在您的情况下,这意味着您必须显式声明一个构造函数和析构函数.将您的代码更改为:

In your case this means that you have to explicitly declare a constructor and destructor. Change your code to:

typedef struct
{
    enum v{a,b,c} v;
    union w{
        int a;
        bool b;
        std::string c;
        w() {}       // Explicit constructor definition
        ~w() { };    // Explicit destructor definition
} w;

} Data_Set2;

这应该有效.

正如我在评论中已经提到的那样,您应该看看 std :: any std :: variant .后者提供类型安全的联合,并且在您的情况下可能是更好的选择.请注意,您的编译器(显然是MSVC)需要支持C ++ 17.

As already stated in my comment, you should however have a look at std::any and std::variant. The latter provides type-safe unions and would probably be the better choice in your case. Note that your compiler (apparently MSVC) needs to support C++17.

如eerorika所评论,您需要确保仅在当前活动的成员上调用它.开头链接的参考文献显示了一个字符串/向量联合的示例,以及该示例如何为未定义的行为引入了许多陷阱.因此,除非您只是想了解幕后发生的事情或使用POD类型,否则我建议您改为使用 std :: variant .

As commented by eerorika, you will need to make sure that you only call it on the currently active member. The reference linked in the beginning shows an example for a string/vector union and how it introduces many pitfalls for undefined behavior. So unless you're just trying to understand what's happening behind the scenes or using POD types, I'd advise you work with std::variant instead.

这篇关于在结构的并集成员中使用std :: string时,不能引用默认构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆