编译器是否可以通过直接初始化来替代复制初始化?
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++入门文章中的陈述与引用的帖子?
是的,这是许多情形之一,通过复制省略的规则支配([class.copy]),其中,所述编译器可以产生暂时对象,但这样做并不是必需的。
形式上,当你u
是U
类型的值并T
是从U
构造的,则初始化T t = u;
意味着t
是从u
构造为如果写T t = T(u);
临时构成。然而,这个副本可能(通常是是)消失了,效果是T t(u);
,只有复制初始化要求构造函数是非显式的。
但是我引用的帖子呢?在这种情况下,符合前提条件,并且通过使用直接初始化来获得不同的结果... – AlwaysLearning
@MeirGoldenberg:即使复制构造函数具有副作用,复制elision的规则也明确允许elision。所以你可以根据使用的临时对象的数量确实得到不同的输出。 –
你的意思是说引用文章中的代码是未定义行为的例子吗? – 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
在这种情况下,你正在使用'std :: string',所以我认为没有什么区别。 – coincoin
@coincoin我意识到这一点,并添加了“(一般)”这几个字,清楚地表明我在最一般的语境中引用了编译器的这种行为。我相信** C++ Primer **意味着一般的上下文,尽管他们在字符串中使用了这个例子。 – AlwaysLearning