如何确保在 C++ 中的 Class 模板中正确初始化非静态数据成员
How to Ensure proper initialization of Non Static Data Members within a Class Template in C++
我正在使用 C++ 中的模板,想知道我们如何正确(值)初始化 class 模板中的非静态数据成员。例如,考虑以下片段:
template<typename T>
class MyVector
{
T x; // x has undefined value for a built in type
};
现在我知道数据成员 x
对于 local/block 范围内的内置类型具有 垃圾值 除非显式初始化。
所以我想对数据成员进行值初始化。如果我将上面的代码修改为:
template<typename T>
class MyVector
{
T x(); // now x becomes a member function
};
从上面修改后的代码片段可以看出,x
现在是一个成员函数。我如何 value 初始化 类型 T
的数据成员 x
?
您可以使用 default member initializer (C++11 起),它只支持等号或大括号初始化器,但不支持圆括号。
template<typename T>
class MyVector
{
T x{};
// or
T x = T();
};
或者提供一个带有成员初始值设定项列表的用户定义的构造函数。
template<typename T>
class MyVector
{
T x;
MyVector() : x() {}
};
根据您使用的 C++ 版本,有不同的方法可以完成您想要的操作。这在下面有更详细的解释:
C++11
template<typename T>
class MyVector
{
T x{};
};
C++11 之前
template<typename T>
class MyVector
{
T x;
MyVector(): x()
{
}
};
C++11
从 C++11 开始,您还可以编写(使用 构造函数初始化列表):
template<typename T>
class MyVector
{
T x;
MyVector(): x{}
{
}
};
C++11
请注意,此版本 won't work if 用于复制初始化的构造函数是 显式 因为没有强制性的 copy elison。
#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;
}
但是上面的版本will work用C++17因为在C++17中有强制复制elison
#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; //works with C++17 due to mandatory copy elison
return 0;
}
我正在使用 C++ 中的模板,想知道我们如何正确(值)初始化 class 模板中的非静态数据成员。例如,考虑以下片段:
template<typename T>
class MyVector
{
T x; // x has undefined value for a built in type
};
现在我知道数据成员 x
对于 local/block 范围内的内置类型具有 垃圾值 除非显式初始化。
所以我想对数据成员进行值初始化。如果我将上面的代码修改为:
template<typename T>
class MyVector
{
T x(); // now x becomes a member function
};
从上面修改后的代码片段可以看出,x
现在是一个成员函数。我如何 value 初始化 类型 T
的数据成员 x
?
您可以使用 default member initializer (C++11 起),它只支持等号或大括号初始化器,但不支持圆括号。
template<typename T>
class MyVector
{
T x{};
// or
T x = T();
};
或者提供一个带有成员初始值设定项列表的用户定义的构造函数。
template<typename T>
class MyVector
{
T x;
MyVector() : x() {}
};
根据您使用的 C++ 版本,有不同的方法可以完成您想要的操作。这在下面有更详细的解释:
C++11
template<typename T>
class MyVector
{
T x{};
};
C++11 之前
template<typename T>
class MyVector
{
T x;
MyVector(): x()
{
}
};
C++11
从 C++11 开始,您还可以编写(使用 构造函数初始化列表):
template<typename T>
class MyVector
{
T x;
MyVector(): x{}
{
}
};
C++11
请注意,此版本 won't work if 用于复制初始化的构造函数是 显式 因为没有强制性的 copy elison。
#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;
}
但是上面的版本will work用C++17因为在C++17中有强制复制elison
#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; //works with C++17 due to mandatory copy elison
return 0;
}