Alb*_*ert 3 c++ variables initialization declaration
我发现有时候我必须手动初始化所有POD类型.例如
struct A {
int x;
/* other stuff ... */
A() : x(0) /*...*/ {}
A(/*..*/) : x(0) /*...*/ {}
};
Run Code Online (Sandbox Code Playgroud)
我不喜欢这个有几个原因:
为了解决这个问题,我尝试使用自己的类型.即不使用int x,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 ... */
};
Run Code Online (Sandbox Code Playgroud)
到目前为止,这基本上解决了我想要初始化的所有情况0(这是迄今为止最常见的情况).
感谢James McNellis的提示:这也可以通过boost::value_initialized.
现在,不限于POD类型:
但有时我想用不同的东西进行初始化,再次出现问题,因为Num模板结构不能轻易扩展到允许的范围.基本上是因为我不能将浮点数(例如float)作为模板参数传递.
在Java中,我会这样做:
class A {
int x = 42;
/*...*/
public A() {}
public A(/*...*/) { /*...*/ }
public A(/*...*/) { /*...*/ }
/*...*/
}
Run Code Online (Sandbox Code Playgroud)
我觉得非常重要的是,在这种情况下,你想在所有可能的构造函数中以相同的方式初始化成员变量,你可以直接在成员变量旁边写入init值,就像在int x = 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; } \
}
Run Code Online (Sandbox Code Playgroud)
(对于其他编译器,我可以省略_LINENAME该结构的名称,只是将其保留为未命名.但MSVC不喜欢它.)
现在这或多或少都像我想要的那样.现在它看起来像:
struct A {
PIVar(int,42) x;
/*...*/
A() {}
A(/*...*/) { /*...*/ }
A(/*...*/) { /*...*/ }
/*...*/
};
Run Code Online (Sandbox Code Playgroud)
虽然它做了我想要的(大多数),但我仍然不满意它:
PIVar(代表PreInitVar),但我真的无法想出更好的东西.与此同时,我希望简短.你怎么解决这个问题?更好的解决方案?
有一个答案再次删除,表示C++ 0x允许基本上与Java相同的语法.真的吗?那么我只需要等待C++ 0x.
请不要给出任何评论:
另外,请不要告诉我不要使用它.我知道我当前解决方案的所有缺点.如果您确定我不知道这一点,请仅对非明显的缺点发表评论.请不要只说我当前的解决方案有许多缺点.另请注意,使用它并不会更糟.我只是问你是否知道一个比我在这里提出的解决方案更好的解决方案.
sbi*_*sbi 10
有时,我必须实现构造函数的唯一原因是因为这个原因.
你不必那样做.
struct POD {
int i;
char ch;
};
POD uninitialized;
POD initialized = POD();
Run Code Online (Sandbox Code Playgroud)
同样在初始化列表中:
class myclass
POD pod_;
// ....
myclass()
: pod_() // pod_'s members will be initialized
{
}
Run Code Online (Sandbox Code Playgroud)
为了解决这个问题,我尝试使用自己的类型.
您的类型在此方案中失败:
void f(int&);
Num<int> i;
f(i);
Run Code Online (Sandbox Code Playgroud)
可能会有更多问题,但这就是我立刻想到的.
你怎么解决这个问题?更好的解决方案?
是的,我们都解决了这个问题.我们没有尝试对抗语言,而是按照创建方式使用它:初始化初始化列表中的POD.当我看到这个:
Run Code Online (Sandbox Code Playgroud)struct ML_LieroX : MapLoad { std::string id; PIVar(int, 0) type; std::string themeName; PIVar(int, 0) numObj; PIVar(bool,false) isCTF;
我畏缩.这是做什么的?为什么会这样?这甚至是C++吗?
所有这些只是为了节省一些键入初始化列表的键击?你是认真的吗?
这是一个旧的bon mot:一段代码被写入一次,但在其生命周期内将被读取数十,数百甚至数千次.这意味着,从长远来看,编写一个代码所花费的时间或多或少是可以忽略的.即使你花了十倍的时间来编写适当的构造函数,但它节省了我理解代码所需时间的10%,那么编写构造函数就是你应该做的.
| 归档时间: |
|
| 查看次数: |
4255 次 |
| 最近记录: |