加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

C:自动初始化

发布时间:2020-12-16 10:42:47 所属栏目:百科 来源:网络整理
导读:我发现有时候我必须手动初始化所??有POD类型.例如. struct A { int x; /* other stuff ... */ A() : x(0) /*...*/ {} A(/*..*/) : x(0) /*...*/ {}}; 我不喜欢这个有几个原因: 我必须在每个构造函数中重做它. 初始值与变量声明位于不同的位置. 有时我必须实
我发现有时候我必须手动初始化所??有POD类型.例如.

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

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

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

>我必须在每个构造函数中重做它.
>初始值与变量声明位于不同的位置.
>有时我必须实现构造函数的唯一原因是因为这个原因.

为了解决这个问题,我尝试使用自己的类型.即而不是使用int x,y;,我使用自己的vector struct,它也会自动初始化为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)作为模板参数传递.

在Java中,我会这样做:

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

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

我觉得非常重要的是,在这种情况下,你想在所有可能的构造函数中以相同的方式初始化一个成员变量,你可以直接在成员变量旁边写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; } 
}

(对于其他编译器,我可以省略结构的_LINENAME名称,只保留未命名.但是MSVC不喜欢它.)

现在这或多或少都像我想要的那样.现在它看起来像:

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

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

虽然它做了我想要的(大多数),但我仍然不满意它:

>我不喜欢名字PIVar(代表PreInitVar),但我真的想不出更好的东西.与此同时,我希望简短.
>我不喜欢那个宏观黑客.

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

有一个答案再次被删除,表示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.当我看到这个:

06003

我畏缩.这是做什么的?为什么会这样?这甚至是C吗?

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

这是一个旧的bon mot:一段代码被写入一次,但在其生命周期内将被读取数十,数百甚至数千次.这意味着,从长远来看,编写一个代码所花费的时间或多或少是可以忽略的.即使你花了十倍的时间来编写适当的构造函数,但它节省了我理解代码所需时间的10%,那么编写构造函数就是你应该做的.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读