这里是source.cpp的源代码。
#include <iostream>
struct A {
A(int i) : i(i) { std::cout << this << ": A(int)" << std::endl; }
A(A const &a) : i(a.i) { std::cout << this << ": A(A const &)" << std::endl; }
A(A &&a) : i(a.i) { std::cout << this << ": A(A &&)" << std::endl; }
~A() { std::cout << this << ": ~A()" << std::endl; }
private:
int i;
};
int main() {
std::cout << "#1 :" << std::endl;
A a1 = 1; // #1, copy-initialization
std::cout << "#2 :" << std::endl;
A a3(1); // #2, direct-initialization
std::cout << "#3 :" << std::endl;
A a4 = {1}; // #3, copy-list-initialization
std::cout << "#4 :" << std::endl;
A a5{1}; // #4, direct-list-initialization
std::cout << std::endl;
return 0;
}
使用以下命令编译上述代码:clang++ -std=c++14 -Wall -fno-elide-constructors -pedantic -o main.exe source.cpp
(这里我禁用了构造优化。顺便说一下,我使用的是Clang 3.8.1)。然后,我得到了以下输出:
#1 :
0x61fe40: A(int)
0x61fe48: A(A &&)
0x61fe40: ~A()
#2 :
0x61fe30: A(int)
#3 :
0x61fe28: A(int)
#4 :
0x61fe20: A(int)
0x61fe20: ~A()
0x61fe28: ~A()
0x61fe30: ~A()
0x61fe48: ~A()
令我惊讶的是,尽管两者都使用了复制初始化,但#3没有先调用
A::A(int)
然后再调用A::A(A &&)
,就像#1那样。我还用gcc 6.1.0进行了测试。同样的事情发生了。据我所知,列表初始化的常见用法之一是禁止缩小转换。我不知道它与编译优化有任何关系。因此,C++语言是否强制使用编译器优化在使用列表初始化时,或者只是编译器更喜欢这样做,还是其他原因导致了上述行为呢?
explicit
构造函数。 - Nicol Bolas