在C#中,我可以这样写:
class AnyThing<T>
{
static public T Default = default(T);
}
static void Main ()
{
int i = AnyThing<int>.Default;
Console.WriteLine (i==0);
string s = AnyThing<string>.Default;
Console.WriteLine (s == null);
}
我打算在C ++中编写一个类似模板类的字典,如果找不到给定的密钥,我希望dict返回通用TVal类型的默认值(零)。在C#中,默认(T)构造来拯救,而在C ++中,我不确定做同样事情的适当方法是什么。
我用gcc4.7尝试了T obj = {}
和T* obj = {}
,效果很好。我只是不确定它是否是语言规范定义的语法,如果这种类型的代码将是可移植的交叉编译器和平台。我的doudt请帮帮我!提前谢谢!
PS:
~~~~~~~~~~
为了确保模板获得任何类型的默认(零输出)值,即使是那些没有可调用默认ctor的值,我采用了以下机制(受avakar的回答启发):
template<class T>
struct AnyThing
{
static const T& Default ;
private:
static const char temp[sizeof(T)];
};
template<class T> const char AnyThing<T>::temp[] = {};
template<class T> const T& AnyThing<T>::Default = *(T*)temp;
struct st
{
double data;
st()=delete;
};
int main()
{
cout << (int)AnyThing<char*>::Default<<endl; //0
cout << AnyThing<int>::Default<<endl; //0
cout <<AnyThing<st>::Default.data<<endl; //0
}
它看起来很丑,但不应该造成任何麻烦,毕竟归零的对象只是一块空白内存。我错了吗?
答案 0 :(得分:22)
在C ++中,C#中没有类似default
关键字的内容。由于默认构造函数为private
,因此默认情况下初始化类型的值构造函数将失败。在C#中,如果默认构造函数是私有的,则class-type的值将初始化为null
,因为类类型为reference-type
。
{}
的初始化由语言规范定义。这是C ++ 11。在C ++ 03中,您应该使用
T obj = T();
正如评论中 bames53 指出的那样,当你想初始化T*
时,你应该使用
在C ++ 11之前。
T* obj = 0;
或
T* obj = NULL;
在C ++ 11中。
T* obj = {};
或
T* obj = nullptr;
答案 1 :(得分:5)
从Bjarne Stroustrup的“C ++编程语言,第三版”中汲取文字:
BEGIN QUOTE
4.9.5初始化[dcl.init]
如果为对象指定了初始化程序,则该初始值设定项确定对象的初始值。如果未指定初始化程序,则将全局(第4.9.4节),名称空间(第8.2节)或本地静态对象(第7.1.2节,第10.2.2节)(统称为静态对象)初始化为适当类型的0 。例如:
int a; // means int a=0;
double d; // meands d=0;
默认情况下,不会初始化本地变量(有时称为自动对象)和在空闲存储上创建的对象(有时称为动态对象或堆对象)。例如:
void f()
{
int x; // x does not have a well-defined value
// . . .
}
数组和结构的成员是默认初始化的,具体取决于数组或结构是否为静态。用户定义的类型可能已定义默认初始化(第10.4.2节)。
更复杂的对象需要多个值作为初始化程序。这由由{和}分隔的初始化列表处理,用于数组的C风格初始化(第5.2.1节)和结构(第5.7节)。
对于带有构造函数的用户定义类型,使用函数式参数列表(§2.5.2,§10.2.3)。请注意,声明中的一对空括号()始终表示''function''(第7.1节)。例如:
int a[] = {1,2}; // array initializer
Point z(1,2); // function-style initializer (initialization by constructor)
int f(); // function declaration
结束语录
因此,您可以从该类型的静态对象中获取任何类型的默认值:
static T defaultT; // `defaultT' has de default value of type T
答案 2 :(得分:3)
如果T
没有复制构造函数,ForEveR的答案将无效。在C ++ 03中,无法对初始化和优雅的变量进行零初始化。剩下的就是以下技巧。
T temp[1] = {};
T & obj = temp[0];
此处,temp[0]
为零初始化,然后绑定到obj
。不需要复制构造函数。
答案 3 :(得分:2)
创建您自己的默认关键字:
class default_t
{
public:
template<typename T>
operator T() const { return T(); }
};
default_t const default = default_t();
使用它像:
int myInt = default;
vector<string> myVector = default;
shared_ptr<string> myPtr = default;
或者有轻微的语义变化:
default_t const empty = default_t();
vector<Persons> fetchPersons()
{
if (Database::isConnected())
{
return Database::fetchPersons();
}
return empty;
}