c++ 11 允许类内定义时直接初始化非静态成员变量的几点疑惑

QuantumEnergy 2016-08-18 12:34:48
这样是不是说明在类的定义时就分配内存?

class BASE {

public:
int *i = new int(5); //ok
BASE base; //error 因为会引起递归定义
BASE *base_0 = new BASE(); //error 如何理解?
static const BASE base_1; //ok 因为在全局区分配
static BASE base_2; //ok 因为在全局区分配
~BASE() {
cout << "~";
}

};


BASE *base_0 = new BASE(); //这句错误? 如何理解? 和内存分配时间有关系? 还是说和构造函数时机?
...全文
429 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
ri_aje 2016-08-19
  • 打赏
  • 举报
回复
new int 那句初始化最终变成所有构造函数的一部分,除非该构造函数的 member init list 里面明确对 int i 初始化了,这时构造函数的初始化优先。 new 操作符要完整类型,BASE 在 BASE 里面的时候还是不完整类型呢,所以出错。
ri_aje 2016-08-19
  • 打赏
  • 举报
回复
引用 9 楼 QuantumEnergy 的回复:
[quote=引用 4 楼 ri_aje的回复:]new int 那句初始化最终变成所有构造函数的一部分,除非该构造函数的 member init list 里面明确对 int i 初始化了,这时构造函数的初始化优先。 new 操作符要完整类型,BASE 在 BASE 里面的时候还是不完整类型呢,所以出错。
哦哦,new在此处已经要求类型完整了呀,有这样考虑过,没敢太确定。然后还有就是发现如果此处显示定义构造函数,编译可以正常通过(gcc编译),当然实例化肯定会由于递归而出错,此处不关心这个。所以构造函数和成员变量的时机具体是? new这里应该是不会分配内存,只是告诉编译器需要4个字节空间,那要求类型完整的原因或者目的是?[/quote] 4 楼我说错了,new BASE 的时候 BASE 视同完整的,标准特许的。 不过这里要求一个你自己写的默认构造函数,否则 new BASE 的时候要调用默认构造函数,后者继续调用 new BASE,造成死循环了。
ri_aje 2016-08-19
  • 打赏
  • 举报
回复
引用 5 楼 xsklld 的回复:
[quote=引用 4 楼 ri_aje 的回复:] new int 那句初始化最终变成所有构造函数的一部分,除非该构造函数的 member init list 里面明确对 int i 初始化了,这时构造函数的初始化优先。 new 操作符要完整类型,BASE 在 BASE 里面的时候还是不完整类型呢,所以出错。
在这里BASE被认为是完整类型。参见N4606/class.mem/Paragraph 6:
引用
... Within the class member-specification, the class is regarded as complete within function bodies, default arguments, exception-specifications, and default member initializers (including such things in nested classes). ...
比如

class A {
    A() : p(nullptr) {}
    A *p = new A;  // 可以通过编译
};
[/quote] 嗯,你说的对,我疏忽了。default member init 是新加的,我以为没有特权呢。主楼的错误是因为缺默认构造函数。
paschen 版主 2016-08-19
  • 打赏
  • 举报
回复
就样就递归申请了..
  • 打赏
  • 举报
回复
引用 9 楼 QuantumEnergy 的回复:
[quote=引用 4 楼 ri_aje的回复:]new int 那句初始化最终变成所有构造函数的一部分,除非该构造函数的 member init list 里面明确对 int i 初始化了,这时构造函数的初始化优先。 new 操作符要完整类型,BASE 在 BASE 里面的时候还是不完整类型呢,所以出错。
哦哦,new在此处已经要求类型完整了呀,有这样考虑过,没敢太确定。然后还有就是发现如果此处显示定义构造函数,编译可以正常通过(gcc编译),当然实例化肯定会由于递归而出错,此处不关心这个。所以构造函数和成员变量的时机具体是? new这里应该是不会分配内存,只是告诉编译器需要4个字节空间,那要求类型完整的原因或者目的是?[/quote] 指针不会递归出错啊。
  • 打赏
  • 举报
回复
先声明个默认构造函数就行了.

class BASE {
 
public:
	BASE();
     int *i = new int(5);  //ok
     //BASE base;   //error   因为会引起递归定义
     BASE *base_0 = new BASE();     //error  如何理解?
     static const BASE base_1;      //ok 因为在全局区分配
     static BASE base_2;      //ok  因为在全局区分配
    ~BASE() {
    }
};
QuantumEnergy 2016-08-19
  • 打赏
  • 举报
回复
引用 4 楼 ri_aje的回复:
new int 那句初始化最终变成所有构造函数的一部分,除非该构造函数的 member init list 里面明确对 int i 初始化了,这时构造函数的初始化优先。 new 操作符要完整类型,BASE 在 BASE 里面的时候还是不完整类型呢,所以出错。
哦哦,new在此处已经要求类型完整了呀,有这样考虑过,没敢太确定。然后还有就是发现如果此处显示定义构造函数,编译可以正常通过(gcc编译),当然实例化肯定会由于递归而出错,此处不关心这个。所以构造函数和成员变量的时机具体是? new这里应该是不会分配内存,只是告诉编译器需要4个字节空间,那要求类型完整的原因或者目的是?
QuantumEnergy 2016-08-19
  • 打赏
  • 举报
回复
引用 2 楼 Saingel的回复:
递归申请内存,机器boom
没有实例化,只是定义这样的一个类
QuantumEnergy 2016-08-19
  • 打赏
  • 举报
回复
引用 1 楼 幻夢之葉的回复:
你类都没定义完,编译器怎么知道你类的大小?不知道大小那该分配多少内存? 跟你第一个error是一个意思! 你可以定义一个指针,因为只需要分配一个指针的空间而已,并不涉及到计算和分配内存
我是定义BASE类型指针呀,也就是说会知道将来如果实例化需要四个字节,我只是定义,没有在程序中任何实例化,编译也出错,如果实例化,肯定会出错,这个因为递归,可是单纯定义也不能编译通过?
sdghchj 2016-08-19
  • 打赏
  • 举报
回复
在定义时初始化只是方便写代码,编译器会把初始化转移到构造函数。而即便是在构造函数里这样去new,也会导致递归构造,跟是否在定义时直接初始化没必要联系。
xskxzr 2016-08-19
  • 打赏
  • 举报
回复
引用 4 楼 ri_aje 的回复:
new int 那句初始化最终变成所有构造函数的一部分,除非该构造函数的 member init list 里面明确对 int i 初始化了,这时构造函数的初始化优先。 new 操作符要完整类型,BASE 在 BASE 里面的时候还是不完整类型呢,所以出错。
在这里BASE被认为是完整类型。参见N4606/class.mem/Paragraph 6:
引用
... Within the class member-specification, the class is regarded as complete within function bodies, default arguments, exception-specifications, and default member initializers (including such things in nested classes). ...
比如

class A {
    A() : p(nullptr) {}
    A *p = new A;  // 可以通过编译
};
xskxzr 2016-08-18
  • 打赏
  • 举报
回复
这条语句在运行时会陷入无穷递归,无穷尽地构造BASE。 至于为什么会在编译时报错,是因为标准有明确的规定(N4606/class.mem/Paragraph 8):
引用
... A brace-or-equal-initializer for a non-static data member specifies a default member initializer for the member, and shall not directly or indirectly cause the implicit definition of a defaulted default constructor for the enclosing class or the exception specification of that constructor.
Saingel 2016-08-18
  • 打赏
  • 举报
回复
递归申请内存,机器boom
幻夢之葉 2016-08-18
  • 打赏
  • 举报
回复
你类都没定义完,编译器怎么知道你类的大小?不知道大小那该分配多少内存? 跟你第一个error是一个意思! 你可以定义一个指针,因为只需要分配一个指针的空间而已,并不涉及到计算和分配内存

64,681

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧