Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/164.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;:自动初始化_C++_Variables_Initialization_Declaration - Fatal编程技术网

C++ C++;:自动初始化

C++ C++;:自动初始化,c++,variables,initialization,declaration,C++,Variables,Initialization,Declaration,我发现有时我不得不手动初始化所有POD类型,这很烦人。例如 struct A { int x; /* other stuff ... */ A() : x(0) /*...*/ {} A(/*..*/) : x(0) /*...*/ {} }; 我不喜欢这样有几个原因: 我必须在每个构造函数中重做这个 初始值与变量声明位于不同的位置 有时我必须实现构造函数的唯一原因就是因为这个 为了克服这个问题,我尝试使用我自己的类型。即,不使用intx,y,我使用自己的

我发现有时我不得不手动初始化所有POD类型,这很烦人。例如

struct A {
    int x;
    /* other stuff ... */

    A() : x(0) /*...*/ {}
    A(/*..*/) : x(0) /*...*/ {}
};
我不喜欢这样有几个原因:

  • 我必须在每个构造函数中重做这个
  • 初始值与变量声明位于不同的位置
  • 有时我必须实现构造函数的唯一原因就是因为这个
为了克服这个问题,我尝试使用我自己的类型。即,不使用
intx,y,我使用自己的向量结构,它也会使用
0
自动初始化。我还考虑了实现一些简单的包装器类型,如:

template<typename T>
struct Num {
    T num;
    Num() : num(0) {}
    operator T&() { return num; }
    operator const T&() const { return num; }
    T& operator=(T _n) { num = _n; return num; }
    /* and all the other operators ... */
};
我发现非常重要的一点是,在这种情况下,您希望在所有可能的构造函数中始终以相同的方式初始化成员变量,您能够直接在成员变量旁边写入init值,如
intx=42

所以我试图解决的问题是在C++中做同样的事情。 为了克服无法通过模板参数传递init值的问题,我拼凑了一个丑陋的宏:

#define _LINENAME_CAT( name, line ) name##line
#define _LINENAME( name, line ) _LINENAME_CAT( name, line )

/* HACK: use _LINENAME, workaround for a buggy MSVC compiler (http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=360628)*/
#define PIVar(T, def) \
struct _LINENAME(__predef, __LINE__) { \
 typedef T type; \
 template<typename _T> \
 struct Data { \
  _T var; \
  Data() : var(def) {} \
 }; \
 Data<T> data; \
 T& operator=(const T& d) { return data.var = d; } \
 operator const T&() const { return data.var; } \
 operator T&() { return data.var; } \
}
虽然它满足了我的需求(大部分),但我仍然不完全满意:

  • 我不喜欢这个名字
    PIVar
    (它代表
    PreInitVar
    ),但我真的想不出更好的名字了。同时,我想把它剪短
  • 我不喜欢那种宏破解

你是怎么解决的?有更好的解决办法吗


有一个答案再次被删除,它说C++0x允许基本上与Java中相同的语法。这是真的吗?所以我只能等待C++0x


请不要给出任何评论,如:

    “然后只使用java代替”/“不要使用C++”或“”
  • “如果你需要这样的东西,你可能做错了”或者
  • “不要这样做”
另外,请不要告诉我不要使用它。我知道我当前解决方案的所有缺点。如果你真的确定我没有意识到这一点,请只对不明显的缺点发表评论。请不要只是说我目前的解决方案有很多缺点。也请不要声明使用它不会更糟。我只是问你是否知道一个比我在这里介绍的更好的解决方案

有时我必须实现构造函数的唯一原因就是因为这个

你不必那么做

struct POD {
  int i;
  char ch;
};

POD uninitialized;

POD initialized = POD();
在初始化列表中:

class myclass
  POD pod_;
  // ....
  myclass()
   : pod_() // pod_'s members will be initialized
  {
  }

为了克服这个问题,我尝试使用我自己的类型

在这种情况下,您的类型失败:

void f(int&);

Num<int> i;
f(i);
我畏缩。这是干什么的?为什么是这样?这是C++吗? 所有这些仅仅是为了节省键入初始化列表的几次击键?你是认真的吗


这里有一句古老的箴言:一段代码编写一次,但在它的生命周期中,将被读取数十次、数百次甚至数千次。这意味着,从长远来看,编写一段代码所需的时间或多或少是可以忽略的。即使编写正确的构造函数需要十倍的时间,但它为我节省了理解代码所需的10%的时间,那么编写构造函数就是你应该做的

Boost提供了一个
value_initialized
模板,可用于确保对象(POD或not)的值已初始化。非常详细地解释了使用它的优缺点


你抱怨不能将一个对象自动初始化为给定的值,这没有多大意义;与被吊舱的物体无关;如果要使用非默认值初始化非POD类型,则必须在初始化时指定该值。

可以按如下方式初始化POD结构:

struct POD
{
    int x;
    float y;
};

int main()
{
    POD a = {};            // initialized with zeroes
    POD b = { 1, 5.0f };   // x = 1, y = 5.0f

    return 0;
}
有一种方法可以实现这一点:

struct A {
    int x = 42;
};
这正是我想要的

如果该建议没有进入最终版本,则可能是至少避免在每个构造函数中重新编码初始化的另一种方法(同时避免使用伪帮助函数来完成此操作)


<>在当前C++中,不管我已经演示了什么,似乎没有更好的方法来做。

< P> C++有构造函数委托,为什么不使用它?
struct AState
{
    int x;
    AState() : x(42) {}
};

class A : AState
{
    A() {}
    A(/*...*/) { /*...*/ }
    A(/*...*/) { /*...*/ }
};

现在,
x
的初始化由所有构造函数委派。基本构造函数甚至可以接受从C++0x之前的
A::A

的每个版本传递的参数。如果要初始化的非零值不是完全任意的(实际上通常是这样),则有一个解决方案可以很好地工作。类似于boost::initialized_value,但是有一个额外的参数来获取初始值(由于C++,这有点麻烦)

template结构默认值{T operator()(){return T();};
模板结构调用{T operator()(){return F();}};
模板结构整数{int运算符(){return N;}};
模板
类已初始化{
公众:
已初始化():x(值()){}
已初始化(常数X&X_uux):X(X_ux{}
常量X&get()常量{return X;}
运算符常量X&()常量{return X;}
运算符X&({return X;}
私人:
X;
};
您可以这样使用它:

struct Pi { double operator()() { return 3.14; } }; //Exactly
const char* init_message() { return "initial message"; }
Point top_middle() { return Point(screen_width()/2, 0); }

struct X {
  initialized<int> a;
  initialized<int, Integer<42> > b;
  initialized<double> c;
  initialized<double, Pi> d;
  initialized<std::string> e;
  initialized<std::string, Call<const char*, init_message> > f;
  initialized<Point> g;
  initialized<Point, Call<Point,top_middle> > h;
  X() {}
};
struct Pi{double operator(){return 3.14;}//确切地
const char*init_message(){返回“初始消息”;}
点顶部_中间(){返回点(屏幕宽度()/2,0);}
结构X{
初始化a;
初始化b;
初始化c;
初始化d;
初始化e;
初始化f;
初始化g;
初始化h;
X(){}
};
我发现必须创建一个伪函数来返回任何非整数/非默认值的麻烦通常会在整个库中分摊(因为特定类型的非零初始值通常由许多类共享)

显然typedef是这里的朋友

无论如何,我等不及了
struct A {
    int x = 42;
};
struct AState
{
    int x;
    AState() : x(42) {}
};

class A : AState
{
    A() {}
    A(/*...*/) { /*...*/ }
    A(/*...*/) { /*...*/ }
};
template<typename T> struct Default { T operator()() { return T(); } };
template<typename T, T (*F)()> struct Call { T operator()() { return F(); } };
template<int N> struct Integer { int operator()() { return N; } };

template< typename X, typename Value = Default<X> >
class initialized {
public:
  initialized() : x(Value()()) {}
  initialized(const X& x_) : x(x_) {}
  const X& get() const { return x; }
  operator const X&() const { return x; }
  operator X&() { return x; }
private:
  X x;
};
struct Pi { double operator()() { return 3.14; } }; //Exactly
const char* init_message() { return "initial message"; }
Point top_middle() { return Point(screen_width()/2, 0); }

struct X {
  initialized<int> a;
  initialized<int, Integer<42> > b;
  initialized<double> c;
  initialized<double, Pi> d;
  initialized<std::string> e;
  initialized<std::string, Call<const char*, init_message> > f;
  initialized<Point> g;
  initialized<Point, Call<Point,top_middle> > h;
  X() {}
};