gpt4 book ai didi

C++:自动初始化

转载 作者:太空狗 更新时间:2023-10-29 19:37:39 27 4
gpt4 key购买 nike

有时我发现必须手动初始化所​​有 POD 类型很烦人。例如

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

A() : x(0) /*...*/ {}
A(/*..*/) : x(0) /*...*/ {}
};

我不喜欢这个有几个原因:

  • 我必须在每个构造函数中重做此操作。
  • 初始值与变量声明的位置不同。
  • 有时我必须实现构造函数的唯一原因就是因为这个。

为了克服这个问题,我尝试使用自己的类型。 IE。我没有使用 int x,y;,而是使用我自己的 vector 结构,它也使用 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 ... */
};

到目前为止,这基本上解决了所有我想用 0 初始化的情况(这是迄今为止我最常遇到的情况)。

感谢 James McNellis 的提示:这也可以通过 boost::value_initialized 解决.


现在,不限于 POD 类型:

但有时我想用不同的东西初始化,又出现了麻烦,因为 Num 模板结构不能轻易扩展以允许这样做。主要是因为我无法将 float (例如 float)作为模板参数传递。

在 Java 中,我会这样做:

class A {
int x = 42;
/*...*/

public A() {}
public A(/*...*/) { /*...*/ }
public A(/*...*/) { /*...*/ }
/*...*/
}

我发现在这种情况下,如果你想在所有可能的构造函数中始终以相同的方式初始化一个成员变量,你可以将初始化值直接写在成员变量旁边,就像在 int x = 42;.

所以我试图解决的问题是在 C++ 中做同样的事情。

为了克服无法通过模板参数传递初始值的问题,我编写了一个丑陋的宏:

#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; } \
}

(对于其他编译器,我可以省略该结构的 _LINENAME 名称并保持未命名状态。但 MSVC 不喜欢这样。)

现在这或多或少像我想要的那样工作。现在它看起来像:

struct A {
PIVar(int,42) x;
/*...*/

A() {}
A(/*...*/) { /*...*/ }
A(/*...*/) { /*...*/ }
/*...*/
};

虽然它做了我想要的(主要是),但我仍然对它不满意:

  • 我不喜欢 PIVar(代表 PreInitVar)这个名字,但我真的想不出更好的名字。同时,我想缩短它。
  • 我不喜欢那个宏 hack。

你是怎么解决这个问题的?有更好的解决方案吗?


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


请不要发表任何评论:

  • “那就改用Java”/“那就不要用C++”或者
  • “如果你需要这样的东西,你可能做错了什么”或
  • “只是不要这样做”。

另外,请不要告诉我不要使用它。我知道我当前解决方案的所有缺点。如果您确定我不知道,请只对不明显的缺点发表评论。请不要只是说我当前的解决方案有很多缺点。也请不要声明使用它并不差。我只是想问您是否知道比我在这里介绍的解决方案更好的解决方案。

最佳答案

Sometimes the only reason I have to implement a constructor is because of this.

您不必那样做。

struct POD {
int i;
char ch;
};

POD uninitialized;

POD initialized = POD();

同样在初始化列表中:

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

To overcome this, I try to use my own types instead.

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

void f(int&);

Num<int> i;
f(i);

可能还有更多问题,但这是我立即想到的。


How have you solved this? Any better solution?

是的,我们都解决了这个问题。我们并没有试图对抗这门语言,而是按照它创建的方式使用它:在初始化列表中初始化 POD。当我看到这个时:

struct ML_LieroX : MapLoad {        
std::string id;
PIVar(int, 0) type;
std::string themeName;
PIVar(int, 0) numObj;
PIVar(bool,false) isCTF;

我畏缩了。这是在做什么?为什么会这样?这甚至是C++吗?

所有这些只是为了节省输入初始化列表的几次击键?你是认真的吗?

这是一句老话:一段代码只写一次,但在其生命周期内将被阅读数十、数百甚至数千次。这意味着也就是说,从长远来看,编写一段代码所花费的时间或多或少是可以忽略不计的。即使你花十倍的时间来编写正确的构造函数,但它为我节省了 10% 的时间来理解你的代码,那么编写构造函数就是你应该做的。

关于C++:自动初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3771976/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com