T x(value)通常是更好的选择,因为它会直接用值初始化x,而T x = value可能会创建一个临时值,具体取决于值的类型。 在值为T类型的特殊情况下,我的猜测是表达式T x = value将始终导致恰好一个复制构造函数调用。我是对的吗?
我问过这个问题,因为我开始认为第一种语法太丑陋而且难以理解,特别是当值是函数调用的结果时。 例如:
const std::string path(attributes.data(pathAttrib));
const std::string path = attributes.data(pathAttrib);
答案 0 :(得分:5)
T x(value)
通常是更好的选择,因为它会直接用值初始化x,而T x = value
可能会根据值的类型创建一个临时值。
你几乎是对的,更好的选择是最清晰的语法。以下是两者的不同之处:
初始化的形式(使用括号或=)通常是无关紧要的,但是当被初始化的实体具有类类型时会很重要... [8.5 / 11]
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
}
需要进行隐式转换,因此vector<int> v = 3;
之类的内容失败,但看起来不对,对吗?任何副本都可能是elided。我不记得发现这是我写过的任何东西的瓶颈,我很久以前就不再担心了:只需使用最清晰的语法。
在值为T类型的特殊情况下,我的猜测是表达式
T x = value
将始终导致一个复制构造函数调用。我是对的吗?
不,您无法保证始终会调用复制程序,但必须可以访问它。例如,在上面的特定情况下,value
是函数的返回值,标准明确允许省略这些副本。
答案 1 :(得分:1)
从标准的,类型的复制初始化,其中源类型的cv-unqualified类型与目标的派生类相同,具有与直接初始化完全相同的行为。这两种情况的描述引入了一个描述所需行为的段落,即只考虑目标类型的构造函数,并且选择的构造函数用于初始化目标,初始化表达式作为参数。
在这些情况下不允许有额外的临时性。
这两种形式的初始化都不会阻止12.8 [class.copy]中描述的优化。虽然是非规范性示例,但12.8 / 15中的示例使用初始化程序的复制初始化形式来演示消除由于函数将值返回到对象初始值设定项而导致的两个副本。这意味着,如果您的示例中的value
是T
类型的临时值,那么它可能会被删除,而对x
的复制操作可能会被删除。