在堆栈与堆中没有构造函数的结构/类的初始化

initialization of structs/classes without constructors in stack vs heap

本文关键字:结构 初始化 构造函数 堆栈      更新时间:2023-10-16

我想知道C 中没有默认构造函数的Zeroing-Out-Out-Out-Out结构(或类)规则。

尤其是,如果将存储在堆栈中(例如,作为局部变量),它们是不可初学的,但是如果在堆上分配,则它们将被零置化(用GCC 4.9.1进行测试)。保证这是便携式

示例程序:

#include <iostream>
#include <map>
using namespace std;
struct X {
    int i, j, k;
    void show() { cout << i << " " << j << " " << k << endl; }
};
int fib(int i) {
    return (i > 1) ? fib(i-1) + fib(i-2) : 1;
}
int main() {
    map<int, X> m;            
    fib(10);                  // fills the stack with cruft
    X x1;                     // local
    X &x2 = m[1];             // heap-allocated within map
    X *x3 = new X();          // explicitly heap-allocated
    x1.show();  // --> outputs whatever was on the heap in those positions
    x2.show();  // --> outputs 0 0 0 
    x3->show(); // --> outputs 0 0 0     
    return 0;
}

编辑:删除"或者我应该只使用构造函数"在粗体部分中;因为让我问的是我想知道它是否是保证行为 - 我们都可以同意,与显式构造函数相比,可读代码更好。

不是动态分配使您的 struct成员零命名;这是您的语法:

X* ptr = new X();
//            ^^
// 
// as opposed to just:
X* ptr = new X;

如果您要保证它,请继续写下来。:)

一种与自动存储 - 持续等效物相吻合的替代方案是使用较新的{}语法:

X* ptr = new X{};   // dynamic
X  obj{};           // automatic

和带有静态存储持续时间的对象始终是Zero Initialist的,无论如何您默认情况下您都在那里覆盖。

如果要给班级的特定值,请始终使用构造函数。从字面上看,构造函数的目的。您唯一不需要编写设置所需值的构造函数的时间是,如果语言为您提供了一个像复制构造函数为您的构造函数。默认的构造函数不在此列表上的int和其他类型的类型上,因此您必须将构造函数添加到自己的类型中,以适当地设置它们。

只要您没有任何构造函数,所有成员都是公共的,并且不涉及继承,您的结构/类可能是汇总的。

要获取便携式零限制,只需使用执行零Intialization的X x = {};

这是有关聚合的标准报价(8.5.1):

汇总是不提供用户的数组或类(第9条)(第9条) 构造函数(12.1),没有用于非静态的撑杆或平等限制器 数据成员(9.2),没有私人或受保护的非静态数据成员 (第11条),没有基类(第10条),没有虚拟功能 (10.3)。

参考:为什么我不能支撑从另一个结构派生的结构?