考虑以下演示程序。
#include <iostream>
struct A
{
int x;
explicit A( int x = 0 ) : x( x ) {}
};
int main()
{
A a1 { 10 };
std::cout << "a1.x = " << a1.x << '\n';
// A a2 = { 10 };
}
在此声明中
A a1 { 10 };
这里使用了直接初始化。
在注释声明中
// A a2 = { 10 };
也可以像这样重写
// A a2 = 10;
这里使用了复制初始化。但是使用说明符explicit 声明的构造函数。所以编译器会报错。即无法将整数对象10隐式转换为A的类型。
你可以改写
A a2 = A{ 10 };
即显式调用构造函数。
当然对于基本类型没有区别,因为除了在使用大括号初始化时不允许缩小转换之外,没有应用任何构造函数
int x { 1.0 };
类型说明符是占位符auto时有很大的不同。
例如
auto x = 10;
x 的类型为 int。
auto x { 10 };
x 再次具有 int 类型。
auto x = { 10 };
现在x 的类型为std::initializer_list<int>。
例如你可以重写你的循环
for (unsigned int counter{ 1 }; counter <= 20; ++counter) {
以下方式
for ( auto counter{ 1u }; counter <= 20; ++counter) {
但你不能写
for ( auto counter = { 1u }; counter <= 20; ++counter) {
因为在这种情况下,变量counter 的类型是std::initializer_list<unsigned int>。
所以通常你有以下形式的初始化
T x = value;
T x = { value };
T x( value );
T x { value };
例如
#include <iostream>
int main()
{
int x1 = 1;
std::cout << "x1 = " << x1 << '\n';
int x2 = ( 2 );
std::cout << "x2 = " << x2 << '\n';
int x3( 3 );
std::cout << "x3 = " << x3 << '\n';
int x4{ 4 };
std::cout << "x4 = " << x4 << '\n';
}
程序输出是
x1 = 1
x2 = 2
x3 = 3
x4 = 4
但还有另一种情况,您应该使用 T{} 而不是 T() 作为初始值设定项。这是使用模板函数的时候。
考虑以下演示程序
#include <iostream>
template <class>
void f()
{
std::cout << "f<T>() is called\n";
}
template <int>
void f()
{
std::cout << "f<int>() is called\n";
}
int main()
{
f<int()>();
f<int{}>();
}
它的输出是
f<T>() is called
f<int>() is called
用作模板实参的构造int() 指定类型模板实参int,而用作模板实参的构造int{} 指定类型为int 的非类型模板实参等于0 .