C++ 初始化:T x(值)与T x=值(当值为T类型时)

C++ 初始化:T x(值)与T x=值(当值为T类型时),c++,initialization,C++,Initialization,T x(value)通常是更好的选择,因为它将直接用value初始化x,而T x=value可能会根据值的类型创建临时值。 但是,在value为T类型的特殊情况下,我猜想表达式tx=value将始终导致恰好一个拷贝构造函数调用。我说得对吗 我问这个问题是因为我开始认为第一种语法太难看,更难理解,尤其是当值是函数调用的结果时。 e、 g: 常量std::字符串路径(attributes.data(pathAttrib)) const std::string path=attributes.dat

T x(value)通常是更好的选择,因为它将直接用value初始化x,而T x=value可能会根据值的类型创建临时值。 但是,在value为T类型的特殊情况下,我猜想表达式tx=value将始终导致恰好一个拷贝构造函数调用。我说得对吗

我问这个问题是因为我开始认为第一种语法太难看,更难理解,尤其是当值是函数调用的结果时。 e、 g:

  • 常量std::字符串路径(attributes.data(pathAttrib))
  • const std::string path=attributes.data(pathAttrib)
tx(value)
通常是更好的选择,因为它将直接用value初始化x,而
tx=value
可能会根据值的类型创建临时值

你几乎是对的,最好的选择是最清晰的语法。以下是两者的区别:

初始化的形式(使用括号或=)通常是无关紧要的,但当被初始化的实体具有类类型时,它就很重要了。。。[8.5/11]

需要隐式转换,所以像
vectorv=3失败,但这看起来还是错的,对吗?任何副本都有可能。我不记得在我写的任何东西中都发现这是一个瓶颈,很久以前我就不再担心它了:只需使用最清晰的语法


然而,在value为T类型的特殊情况下,我猜想表达式
tx=value
将始终只产生一个拷贝构造函数调用。我说得对吗


不,您不能保证总是调用copy-ctor,但它必须是可访问的。例如,在上面的特定情况下,
value
是函数的返回值,标准明确允许省略这些副本。

从标准中,复制源类型的cv非限定类型与目标类型或派生类相同的类类型的初始化,具有与直接初始化完全相同的行为。这两种情况的描述引入了一个段落,描述了所需的行为,即只考虑目标类型的构造函数,并使用所选构造函数以初始值设定项表达式作为参数初始化目标

在这些情况下,不允许有额外的临时措施


这两种初始化形式都不能阻止12.8[class.copy]中描述的优化发生。虽然是一个非规范性示例,但12.8/15中的示例使用初始值设定项的副本初始化形式来演示如何消除因函数按值向对象初始值设定项返回局部变量而产生的两个副本。这意味着,如果您的示例中的
value
是类型为
T
的临时文件,那么它-以及对
x
的复制操作-可能会被删除。

但是如果
value
是类型为
T
的文件,则没有复制,也没有语义差异,这就是问题所问的。[8.5/14]/14中的任何内容都不能保证没有副本,并且无论是否省略副本,副本仍然适用。但是,是的,我的回答比严格要求的更笼统。我不同意,对于源类型和目标类型相同(模cv限定符和派生类)的直接初始化和复制初始化,只考虑构造函数,并且选择的构造函数与初始值设定项表达式一起用作参数。在这种情况下,编译器没有创建临时副本的许可证。不是临时副本,总是在
ta;tb=a。但是在被问及的情况下,当值由函数返回时,省略copy-ctor是适用的。我明白你的意思了。不过,我们不知道函数是通过值还是通过引用返回。我的理解是,问题在于,在源类型与目标类型相同的情况下,直接初始化是否保证在复制初始化过程中不会额外调用复制构造函数。这是我对标准的解释,两个版本是等效的。显然,在这种特殊的复制初始化情况下,必须选择复制构造函数来初始化目标,初始化器是否是临时的是一个正交问题。
struct A {
  A(int) {}
};
struct B {
  explicit B(int) {}
};

int main() {
  { A obj (42); } // succeeds
  { A obj = 42; } // succeeds

  { B obj (42); } // succeeds
  { B obj = 42; } // fails
}