如何获取任何类型的默认值

Nee*_*eed 7 c++ templates

在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);

    }
Run Code Online (Sandbox Code Playgroud)

我打算在C++中写一个类似模板类的字典,如果找不到给定的密钥,我希望dict返回通用TVal类型的默认值(零输出).在C#中,默认(T)构造来拯救,而在C++中,我不确定做同样事情的适当方法是什么.

我试着T obj = {}T* obj = {}用gcc4.7,它工作得很好.我只是不确定它是否是语言规范定义的语法,如果这种类型的代码将是可移植的交叉编译器和平台.我的doudt请帮帮我!提前致谢!

PS:

~~~~~~~~~~

为了确保模板获得ANY类型的默认(零输出)值,即使是那些没有可调用默认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
}
Run Code Online (Sandbox Code Playgroud)

它看起来很丑,但不应该造成任何麻烦,毕竟归零的对象只是一大块空白内存.我错了吗?

For*_*veR 22

在C++ default中,C#中没有像关键字这样的东西.由于默认构造函数是默认构造函数,因此默认情况下初始化类型的值构造函数将失败private.在C#中,如果默认构造函数是私有的,则class-type的值将被初始化为null,因为class-type是reference-type.

Initialition by {}由语言规范定义.这是C++ 11.在C++ 03中你应该使用

T obj = T();
Run Code Online (Sandbox Code Playgroud)

正如bames53在评论中指出的那样,当你想要初始化时,T*你应该使用

在C++ 11之前.

T* obj = 0;
Run Code Online (Sandbox Code Playgroud)

要么

T* obj = NULL;
Run Code Online (Sandbox Code Playgroud)

在C++ 11中.

T* obj = {};
Run Code Online (Sandbox Code Playgroud)

要么

T* obj = nullptr;
Run Code Online (Sandbox Code Playgroud)

  • @JesseGood`T*t = T*();`虽然工作正常.`T t = T();`当T是指针类型时``也可以正常工作. (3认同)

roy*_*roy 5

摘自"Cj编程语言,Bjarne Stroustrup第三版":

开始报价

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;
Run Code Online (Sandbox Code Playgroud)

默认情况下,不会初始化本地变量(有时称为自动对象)和在空闲存储上创建的对象(有时称为动态对象或堆对象).例如:

void f()
{
   int x;   // x does not have a well-defined value
   // . . . 
}
Run Code Online (Sandbox Code Playgroud)

数组和结构的成员是默认初始化的,具体取决于数组或结构是否为静态.用户定义的类型可能已定义默认初始化(第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
Run Code Online (Sandbox Code Playgroud)

结束语

因此,您可以从该类型的静态对象获取任何类型的默认值:

static T defaultT; // `defaultT' has de default value of type T
Run Code Online (Sandbox Code Playgroud)

  • @ Need4Steed是的,因为C#有引用类型和值类型.所有类类型都是引用类型,可以用null初始化,C++没有这样的东西. (2认同)
  • 最佳答案,直接来自C++的发明者.为什么这个答案得到的答案如此之少?耻辱!谢谢,罗伊. (2认同)

Mar*_*tke 5

创建您自己的默认关键字:

class default_t
{
public:
  template<typename T>
  operator T() const { return T(); }
};

default_t const default = default_t();
Run Code Online (Sandbox Code Playgroud)

像这样使用它:

int myInt = default;
vector<string> myVector = default;
shared_ptr<string> myPtr = default;
Run Code Online (Sandbox Code Playgroud)

或者有轻微的语义变化:

default_t const empty = default_t();

vector<Persons> fetchPersons()
{
  if (Database::isConnected())
  {
    return Database::fetchPersons();
  }

  return empty;
}
Run Code Online (Sandbox Code Playgroud)