Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/135.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++_Struct_Instance Variables - Fatal编程技术网

C++ 尝试初始化构造函数中的数据成员,但失败。为什么?

C++ 尝试初始化构造函数中的数据成员,但失败。为什么?,c++,struct,instance-variables,C++,Struct,Instance Variables,结构指针的成员变量返回了错误的数字 以下是结构声明: struct Obj { int val; Obj(int val) { val = val; } }; 这里是它变得时髦的地方: Obj* cool = new Obj(4); cout << cool->val; // outputs a number that's not 4 cout << (cool->val == 4); // prints 0... interesting

结构指针的成员变量返回了错误的数字

以下是结构声明:

struct Obj {
    int val;
    Obj(int val) { val = val; }
};
这里是它变得时髦的地方:

Obj* cool = new Obj(4);
cout << cool->val; // outputs a number that's not 4
cout << (cool->val == 4); // prints 0... interesting
这:

只是将参数赋值给自身,而将成员变量保留为包含垃圾。你需要:

Obj(int val) : val(val) {}
或者如果您确实需要分配而不是初始化:

Obj(int val) { this->val = val; }
或:

您可能想考虑对成员使用命名约定:

int m_val;
Obj(int val) : m_val(val) {}
为什么我会得到这些奇怪的数字? 您永远不会初始化Obj::val,因此该值正好是在构造Obj实例时该内存位置上的值

原因:这些名字在玩捉迷藏 在Obj的构造函数中,名为val的参数隐藏名为val的数据成员;换句话说,您正在将名为val的参数的值赋给名为val的参数

该标准说,在比以前声明更窄的范围内声明的变量将有效地隐藏旧的

这意味着,由于B处的参数val比a处的范围更窄,因此在C处,编译器认为您引用的是该参数

提议的解决办法 您有几种解决此问题的方法

this->val = val;              // (A)
Obj::val  = val;              // equivalent
A、 使用此->val显式声明要将值分配给Obj的数据成员

B、 使用mem初始值设定项,其中Obj::val不会被参数名隐藏

C、 更改参数的名称

mem初始值设定项看起来很可怕,为什么包括它? 在建议的解决方案中,标有B的解决方案是首选方案

使用mem初始值设定项调用它,并在调用构造函数时直接使用参数val的值初始化成员val;而不是首先必须对其进行默认初始化,然后分配一个值

建议不要使用与成员变量同名的参数,因为如果忘记了名称隐藏,则很容易出错

一种常见的设计是在每个数据成员的前面加上m_,以明确表示该成员确实是实例的成员,如以下代码段中所示:

struct Obj {
    Obj(int val) : m_val (val) { }
    int m_val;
};

这->val=val。您可能应该在打开警告的情况下编译,他们会在心跳中指出这一点。实际上,cool应该是Obj cool4;。你看不到人们在做std::string*s=newstd::stringabc;每次他们需要一个对象时,至少我希望不是。cool->val==4是一个相等检查,因此是bool,如果为false,则为0,如果为true,则为1。正如您在前面的语句中所看到的,cool->val不是4,因此它打印0表示false。可能值得指出在构造函数中初始化数据成员的惯用方法。也就是说,您不会期望这里显示的任何形式是真实代码。我不同意您对解决方案B的偏好。解决方案C比B具有更少的歧义性。我从来没有对C有过任何问题,尤其是在代码审查中。@ThomasMatthews反问:如果数据成员不能,或者最好不应该,您将如何使用选项C,是我的错吗。我不同意B,因为参数名称与数据成员名称相同。我建议:Obj int val:m_valval{}。在我看来,这比保持相同的名称更具可读性。@ThomasMatthews当然,但选项的编写方式显示了所需的最小更改,不过,我将用一条语句更新帖子,说人们应该更愿意重命名数据成员。
struct Obj {
    int val;         // (A)
    Obj(int val) {   // (C)
      val = val;     // (B)
    }
};
this->val = val;              // (A)
Obj::val  = val;              // equivalent
Obj (int val) : val (val) { } // (B)
Obj (int foo) { val = foo; }  // (C)
struct Obj {
    Obj(int val) : m_val (val) { }
    int m_val;
};