gpt4 book ai didi

c++ - 带和不带 ( ) 的构造函数调用之间的区别

转载 作者:IT老高 更新时间:2023-10-28 21:45:40 25 4
gpt4 key购买 nike

我是 C++ 初学者,想了解原因

return std::list<int>();

需要括号,但是

std::list<int> foo;

不需要括号。这些构造函数调用有什么区别?

最佳答案

这些都不是构造函数调用。

第一个是 explicit type conversion ,它创建一个类型为 std::list<int> 的对象.

第二个是变量定义,它创建了一个 std::list<int> 类型的对象。 .

默认构造函数(不带参数的构造函数)在这两种情况下都作为创建的一部分被调用。

尽管您可能会看到诸如“构造函数调用”之类的东西,但在 C++ 中没有显式和单独调用构造函数的语法构造。

一个需要括号而另一个不需要括号的原因是因为它们是两种不同的语言结构,具有不同的语法,而不是两种调用构造函数的方式。


请注意,如果您在第二个示例中添加括号,您实际上是在声明一个函数,而不是定义一个变量:

std::list<int> foo; //variable definition
std::list<int> foo(); //function taking no args, returning a std::list<int>

这通常称为 most-vexing-parse . C++11 引入了支撑初始化来解决这个问题:

std::list<int> foo{}; //variable definition

Standese,适合那些如此倾向的人

(引自 N3337)

“但是 T() 看起来确实像构造函数调用,为什么不是?”

在这种情况下,T()被称为具有函数符号的显式类型转换:

5.2.3 Explicit type conversion (functional notation) [expr.type.conv]

1 [...]

2 The expression T(), where T is a simple-type-specifier or typename-specifier for a non-array complete object type or the (possibly cv-qualified) void type, creates a prvalue of the specified type, which is value-initialized (8.5; no initialization is done for the void() case). [Note: if T is a non-class type that is cv-qualified, the cv-qualifiers are ignored when determining the type of the resulting prvalue (3.10). —end note ]

所以这会创建一个 prvalue,它是 value-initialized

[dcl.init]/7: To value-initialize an object of type T means:

if T is a (possibly cv-qualified) class type (Clause 9) with a user-provided constructor (12.1), then the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);

— [...]

所以这调用构造函数作为值初始化的一部分,这是显式类型转换的一部分。如上所述,没有办法直接调用构造函数。标准说:

[class.ctor]/1: Constructors do not have names. A special declarator syntax is used to declare or define the constructor. The syntax uses:

— an optional decl-specifier-seq in which each decl-specifier is either a function-specifier or constexpr,

— the constructor’s class name, and

— a parameter list

in that order. In such a declaration, optional parentheses around the constructor class name are ignored.

因此构造函数没有名称,我们使用语言定义的语法异常来声明/定义它们。

“这似乎是学术上的区别,这在实践中重要吗?”

也许,也许不是。我的观点是,将上述语法解释为纯构造函数调用描绘了构造函数是什么的错误画面。构造函数初始化一个对象;它不分配该对象的内存、返回初始化的对象、将符号绑定(bind)到该对象或通过变量定义和类型转换完成的任何其他事情。此外,它可能会像 OP 那样造成困惑,因为他认为这两个构造都是构造函数调用,所以他希望使用统一的语法。

当我们有避免混淆的正式术语时,为什么要使用不精确的提喻?

关于c++ - 带和不带 ( ) 的构造函数调用之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33079486/

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