我正在使用 C++ 中的模板,并且想知道如何正确(值)初始化类模板中的非静态数据成员。例如,考虑以下代码片段:
template<typename T>
class MyVector
{
T x; // x has undefined value for a built in type
};
现在我知道数据成员
x
对于本地/块范围内的内置类型具有垃圾值,除非显式初始化。
所以我想对数据成员进行值初始化。如果我将上面的代码修改为:
template<typename T>
class MyVector
{
T x(); // now x becomes a member function
};
从上面修改后的代码片段中可以看出,
x
现在是一个成员函数。我如何值初始化类型x
的数据成员T
?
您可以使用 默认成员初始值设定项 (C++11 起),它仅支持等号或大括号初始值设定项,但不支持括号。
template<typename T>
class MyVector
{
T x{};
// or
T x = T();
};
或者提供带有成员初始值设定项列表的用户定义构造函数。
template<typename T>
class MyVector
{
T x;
MyVector() : x() {}
};
根据您使用的 C++ 版本,有不同的方法可以完成您想要的操作。下面对此进行了更详细的解释:
template<typename T>
class MyVector
{
T x{};
};
template<typename T>
class MyVector
{
T x;
MyVector(): x()
{
}
};
从 C++11 及以后,您还可以编写(使用 构造函数初始值设定项列表):
template<typename T>
class MyVector
{
T x;
MyVector(): x{}
{
}
};
请注意,如果用于复制初始化的构造函数是显式,则此版本将无法工作,因为没有强制的复制省略。
#include <iostream>
using namespace std;
struct Name
{
explicit Name(const Name&)
{
}
Name() = default;
};
template<typename T>
class MyVector
{
public:
T x = T();
};
int main()
{
cout<<"Hello World";
MyVector<int> p; // works with C++11,C++17 etc
MyVector<Name> n; //error with C++11 and C++14
return 0;
}
但是上述版本将适用于 C++17,因为 C++17 中存在强制复制省略。
#include <iostream>
using namespace std;
struct Name
{
explicit Name(const Name&)
{
}
Name() = default;
};
template<typename T>
class MyVector
{
public:
T x = T();
};
int main()
{
cout<<"Hello World";
MyVector<int> p; // works with C++11,C++17 and following
MyVector<Name> n; //works with C++17 due to mandatory copy elision
return 0;
}