编译器是否可以通过直接初始化来替代复制初始化?

问题描述:

C++引物(第5版)第499页上指出,允许编译器代替编译器是否可以通过直接初始化来替代复制初始化?

string null_book = "9-999-9999-9"; // copy initialization 

string null_book("9-999-9999-9"); // compiler omits the copy constructor 

在另一方面,this post显示(通常)在两个表格可以产生不同的结果。

我该如何协调C++入门文章中的陈述与引用的帖子?

+0

在这种情况下,你正在使用'std :: string',所以我认为没有什么区别。 – coincoin

+0

@coincoin我意识到这一点,并添加了“(一般)”这几个字,清楚地表明我在最一般的语境中引用了编译器的这种行为。我相信** C++ Primer **意味着一般的上下文,尽管他们在字符串中使用了这个例子。 – AlwaysLearning

是的,这是许多情形之一,通过复制省略的规则支配([class.copy]),其中,所述编译器可以产生暂时对象,但这样做并不是必需的。

形式上,当你uU类型的值并T是从U构造的,则初始化T t = u;意味着t是从u构造为如果写T t = T(u);临时构成。然而,这个副本可能(通常是)消失了,效果是T t(u);,只有复制初始化要求构造函数是非显式的。

+0

但是我引用的帖子呢?在这种情况下,符合前提条件,并且通过使用直接初始化来获得不同的结果... – AlwaysLearning

+0

@MeirGoldenberg:即使复制构造函数具有副作用,复制elision的规则也明确允许elision。所以你可以根据使用的临时对象的数量确实得到不同的输出。 –

+0

你的意思是说引用文章中的代码是未定义行为的例子吗? – AlwaysLearning

这本书试图说明使用普通C++代码的复制elision。这并不意味着即使在初始化的情况下,编译器也可以将复制初始化更改为直接初始化,但copy-initialization-with-copy-elision与直接初始化具有相同的效果。

允许的可观察行为的唯一变化是消除对复制/移动构造函数和析构函数的调用。所调用的另一个构造函数从不改变。因此:

struct Meow { 
    explicit Meow(int); // #1 
    Meow(double);  // #2 
    Meow(const Meow&); // #3 
}; 

Meow m = 1;  // OK, always call #2, may or may not call #3 
Meow n(1);  // OK, call #1, never call #3 
Meow p = {1}; // Error: copy-list-initialization selected explicit constructor 
Meow q{1};  // OK, call #1, never call #3 
Meow r = {1.0}; // OK, call #2, never call #3