【问题标题】:Difference between T t {x} and T t = { x } for integral or enumeration type?整数或枚举类型的 T t {x} 和 T t = { x } 之间的区别?
【发布时间】:2015-11-20 17:15:23
【问题描述】:

在 C++14 中:

对于任何整数或枚举类型T 和任何表达式expr

两者之间是否有区别:

struct S { T t { expr }; };

struct S { T t = { expr }; };

更新:

我到了[dcl.init.list]p3b5,上面写着:

如果初始化列表有一个类型为 E 的元素,并且 T 不是引用类型或其引用类型与 E 引用相关,则从该元素初始化对象或引用。

我相信这句话适用于 direct-list-initializationcopy-list-initialization

所以我认为答案是否定的,没有区别。

【问题讨论】:

    标签: c++ initialization language-lawyer c++14


    【解决方案1】:

    如果您查看direct initializationcopy initialization 引用,您会发现相同的词:

    如果 T 是非类类型,则在必要时使用标准转换将 other 的值转换为 T 的 cv 非限定版本

    所以应该没有区别。这些初始化的区别仅适用于类类型:复制初始化考虑explicit构造函数和explicit用户定义的转换运算符,直接初始化 确实如此。整型和枚举类型都没有。

    编辑:
    @ᐅ Johannes Schaub - litb ᐊ answered a relative question to this one(仅关于括号,而不是大括号),他用类似的措辞引用了8.5/14(强调我的):

    初始化的形式(使用括号或=)一般为 无关紧要,但在初始化程序或实体时确实很重要 被初始化有一个类类型;见下文。如果实体是 初始化没有类类型,表达式列表在 带括号的初始化程序应为单个表达式。

    我也找不到标准中的{} 对应项。我希望这是足够的论据来支持没有区别的答案。

    【讨论】:

    • 您的链接是关于括号,而不是大括号。尚不清楚这里是否存在相同的论点。
    • 我认为我的答案的前半部分已经足够了。我仍然希望()= (){}= {} 之间的效果保持一致。
    • 好吧,{} vs ={} 符合用户期望,而不是() vs =();考虑:volatile int x = 42; char a(char(x)); char b = (char(x)); char c{char(x)}; char d = {char{x}};
    • 请指出不同之处。你对我的要求太多了。
    • a 不是初始化变量,它是一个函数。
    【解决方案2】:
    1. struct S {T t { expr };}; 是一个非静态数据成员初始化器 不使用等号
    2. struct S{T t = { expr };}; 是一个非静态数据成员初始化器 使用等号

    第一种情况是direct-list-initialization,而第二种情况是copy-list-initialization

    direct-list-initializationcopy-list-initialization 的区别在于,对于第一种情况 both 显式和非显式考虑构造函数,而对于第二个可以调用非显式构造函数。

    为了澄清,请考虑以下示例:

    struct Foo {
      int i;
      explicit Foo(int i_) : i(i_) {}
    };
    
    struct Bar {
      Foo f {1};  
    };
    

    Live Demo

    在此示例中,Foo 有一个 explicit 构造函数,Bar 直接初始化其类型为 Foo 的成员 f。示例代码编译良好,因为对于直接初始化,explicitnon-explicit 构造函数都被考虑在内。

    现在我们通过将不使用等号的非静态数据成员初始化器转换为使用等号的非静态数据成员初始化器的情况,即直接列表初始化的情况来改变示例,即复制列表初始化的一个案例。

    struct Foo {
      int i;
      explicit Foo(int i_) : i(i_) {}
    };
    
    struct Bar {
      Foo f = {1};  
    };
    

    Live Demo

    现在上面的例子没有编译并发出错误:

    错误:选择的构造函数在复制初始化中是显式的

    这是意料之中的,因为正如在复制列表初始化中已经提到的那样,只有非显式构造函数可以调用。

    现在对于枚举器和其他整数类型,上面显示的差异将不适用(即不涉及构造函数)。因此,这两个语句(即 [1] 和 [2])是等价的。

    但为了完整起见,让我们考虑以下示例:

    enum class Foo {A, B, C};
    
    struct Bar {
      Foo f{Foo::A};  
    };
    

    enum class Foo {A, B, C};
    
    struct Bar {
      Foo f = {Foo::A};  
    };
    

    这两个例子都编译得很好。

    还请考虑以下示例:

    struct Bar {
      int i {1};  
    };
    

    struct Bar {
      int i = {1};  
    };
    

    这两个例子都编译得很好。

    【讨论】:

    • “编译良好”和“副作用没有区别”不是等价的陈述。
    • 编译很好是为了说明对于内置类型,提到的差异不适用。因此,对于内置类型,副作用没有区别。
    猜你喜欢
    • 2015-03-21
    • 2019-06-07
    • 1970-01-01
    • 1970-01-01
    • 2015-11-15
    • 2018-01-22
    • 2016-09-07
    • 2011-05-15
    相关资源
    最近更新 更多