#include <iostream>
using namespace std;
class A{
public:
int data[3];
private:
int cnt;
public:
void put(int v){data[cnt++]=v;}
int take(){int c=cnt;cnt=0;return c;}
};
int main() {
A a;
a.take();
a.put(a.take());
a.put(1);
cout<<a.data[0];
return 0;
}
我理解了大部分代码,但是我对函数a.take()感到困惑。在主函数中,我们首先创建一个对象a。然后我们运行a.take()。在此函数中,我们首先让c = cnt,然后将cnt赋值为0。
为什么在为c分配了尚无值的cnt值时没有错误。
如果将此函数写为 int take(){cnt = 0; c = cnt; return c;}
答案 0 :(得分:2)
该代码的作者相信,使用对take()
的初始调用来建立cnt
的{{1}}成员值是符合标准的;他们错了(至少通过C ++ 14,我没有检查过C ++ 17)
按照标准
8.5初始化程序[dcl.init]
- 如果未为对象指定初始化程序,则该对象将被默认初始化。用自动或 获得动态存储持续时间,对象具有不确定性 值,如果没有对该对象执行初始化,则表明 对象保留不确定的值,直到该值被替换 (5.18)。 [注意:具有静态或线程存储持续时间的对象是 零初始化,请参阅3.6.2。 —尾注] 如果不确定的值是 评估产生的行为是不确定的,除了 以下情况:
所有例外都不适用于您,因此我没有显示它们,但您可以查找它们以进行确认。
执行此操作的正确方法是在首次使用之前为0
建立确定值(例如成员初始化列表),然后可以删除无用的cnt
调用。换句话说,
take()
答案 1 :(得分:1)
我们来看看main()
:
A a;
在此步骤中,您创建了类型为a
的对象A
。
a
中有什么?
(1)一个名为data
的公共数据成员,它是int
的数组。
(2)名为cnt
的私有数据成员,它是int
。
请注意,在此步骤中,对象a
已具有这两个数据成员。
它们的价值是另一回事。
(3)公共职能成员take()
和put()
。
a.take()
现在您已经创建了a
,就可以使用它。
a.take()
调用take()
中a
的public成员函数。
在take()
的正文中
int c=cnt;cnt=0;return c;
在返回之前, c
用cnt
的私有数据成员a
的值初始化。
因此可以归结为一个问题:cnt
在这一点上的价值是什么?
您的问题:
为什么在为c分配了尚无值的cnt值时没有错误。
您的措辞不正确。 cnt
确实有价值。但是,在这种情况下,该值是不确定的。也就是说,可以是任何东西。可以是0、42或-123。
详细信息:
由于您没有为类A()
提供默认构造函数A
,因此编译器将为A
生成综合的默认构造函数,该构造函数用于构造{{1 }}。
由于您没有为a
提供类内初始化程序(例如cnt
),因此默认构造函数将默认初始化int cnt = 0;
。
由于cnt
是cnt
,它是内置类型,因此内置类型的默认初始化规则表示:已定义内置类型的变量函数内部未初始化。内置类型的未初始化变量的值是不确定的。
由于int
是在函数a
中定义的,因此main()
具有未定义的值。
答案 2 :(得分:0)
由于cnt
是成员变量(非全局变量),因此其值未初始化,这意味着它可能是该内存位置中的任何值。使用它不是一个错误,但是它将读取的值实际上是垃圾。
请注意,全局变量和静态变量均初始化为0
。