gpt4 book ai didi

c++ - 关于结构初始化语法错综复杂的问题

转载 作者:行者123 更新时间:2023-11-28 07:05:27 24 4
gpt4 key购买 nike

我逐渐积累了一些关于语言初始化语法的开放性问题。当一个人不知道要搜索什么或不知道正确的术语时,搜索答案有时会相对困难。

我在下面的评论中表达的假设是否正确,如果不正确,实际发生了什么?我正在使用 C++11。

struct Foo{};
Foo; //1: Error, this fails for all types, built-in or otherwise
Foo(); //2: rvalue created by an explicit call to the default ctor "Foo::foo()"
Foo{}; //3: rvalue created by specifying an empty initializer list,
// ..at which point is the default constructor called? How
// ..does this actually differ from #2?
Foo={}; //4: Error, why does this syntax not work?
Foo(){}; //5: Error, this one is quite obvious considering #2
Foo()={}; //6: what exactly happens here?
Foo f; //7: instance created by implicit call to default constructor
Foo f{}; //8: instance created by initializer list, similar to #3
Foo f={}; //9: similar to #8
Foo f(); //10: function declaration.
Foo f()={};//11: Error, this is a malformed function declaration
Foo f(){} //12: function definition

最佳答案

初始化是一个令人困惑的话题,因为各种形式的初始化(直接初始化、列表初始化、值初始化等)并不都是相互排斥的。

我浏览了 C++11 标准并阅读了所有血淋淋的细节 ,如果你好奇的话。这是逐行分析。

struct Foo{};

由于 Foo是类类型,默认初始化为 Foo调用默认构造函数(8.5 [dcl.init] 第 6 段)。

由于 Foo是一个非 union 类类型,没有用户提供的构造函数,值初始化为 Foo需要零初始化,然后调用隐式声明的默认构造函数,如果它是非平凡的。 (8.5 [dcl.init] 第 7 段)。

在这种情况下,隐式声明的默认构造函数很简单(12.1 [class.ctor],第 5 段),等效于 Foo::Foo() {} (同上,第 6 段)。
Foo是一个聚合,可以由初始化列表初始化。 (8.5.1 [dcl.init.aggr],第 1 段)
Foo;

畸形。然而,声明 Foo Foo;有效并声明一个名为 Foo 的变量类型 Foo .表达式 Foo;然后将变为有效。不用说,你不应该这样做。
Foo();

这是一个显式类型转换。由于 Foo是非数组完整对象类型,此表达式创建类型为 Foo 的纯右值,它是值初始化的。 (5.2.3 [expr.type.conv] 第 2 段)。
Foo{};

这也是一个显式类型转换,它创建了一个类型为 Foo 的纯右值。这是直接列表初始化的(同上,第 3 段)。由于花括号初始化列表为空且 Foo是具有默认构造函数的类类型,对象是值初始化的(8.5.4 [dcl.init.list],第 3 段)。
Foo={};

好吧,这没有任何意义。你期望它做什么? (注意:同样,如果 Foo 是一个变量,这将变得明确。)
Foo(){};

我同意,很明显这是不正确的,至少作为一种表达方式。然而,它是 Foo 的默认构造函数定义的有效语法。 . (多余的分号是一个空声明。)
Foo()={};

这将创建prvalue Foo()如前所述,然后对其执行分配。这是允许的,即使 Foo()是一个右值(13.5 [over.oper],第 7 段)。这个表达式整体上等价于 Foo().operator=({}) (5.17 [expr.ass],第 9 段)。它构造了一个临时的 Foo通过括号初始化列表中的聚合初始化 {} , 绑定(bind)临时 Foo到右值引用, Foo&& , 并调用 Foo的隐式定义的移动赋值运算符(12.8 [class.copy],第 20-21 段)。
Foo f;

这会调用默认初始化(8.5 [dcl.init],第 11 段)。
Foo f{};

这是列表初始化,因为初始化器是一个花括号初始化列表(8.5 [dcl.init],第 16 段)。具体来说,它是直接列表初始化(8.5.4 [dcl.init.list],第 1 段)。如 Foo{} 的情况,执行值初始化。
Foo f={};

这是复制初始化(8.5 [dcl.init],第 14 段)。同样,由于初始化器是一个花括号初始化列表,它是列表初始化;具体来说,复制列表初始化(8.5.4 [dcl.init.list],第 1 段)。同样,执行值初始化。
Foo f();

这确实是一个函数声明,因为可以解释为函数声明或对象声明的语句总是被解释为前者(8.2 [dcl.ambig.res],第 1 段)。
Foo f()={};

这既不能解释为有效的对象声明,也不能解释为有效的函数声明,因此它是格式错误的。
Foo f(){}

实际上,这是一个函数定义。

关于c++ - 关于结构初始化语法错综复杂的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21822491/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com