C++ C++;:自动初始化
我发现有时我不得不手动初始化所有POD类型,这很烦人。例如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,我使用自己的
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() {}
};