C++:结构体和new关键字

14

我是C++的新手,我有以下代码:

struct Airline {
    string Name;
    int diameter;
    int weight;
};

Airline* myPlane = new Airline;

我的问题是,当我调用new方法时,它会分配内存,如果我没记错的话。特别是考虑到其中有一个字符串类型,PC如何知道要分配多少内存?

谢谢


我的猜测是,如果不了解C++的话,它只存储指向字符串的指针,而实际内容在堆中的某个位置。 - jcomeau_ictx
5个回答

13

std::string是固定大小的对象;它包含一个指向实际字符缓冲区及其长度的指针。 std::string的定义看起来像是这样的:

class string
{
    char *buffer;
    size_t nchars;

  public:
    // interface
};

这意味着您的Airline对象也具有固定的大小。

new不仅分配内存,还初始化对象,包括std::string,这意味着它可能会将char指针设置为0,因为空串。


3

您还可以使用 sizeof 来获取结构的大小:

cout << "sizeof(Airline) = " << sizeof(Airline) << endl;

这是因为编译器了解结构中的字段,并将每个结构成员的大小相加。与您的结构一样,string对象也没有什么不同。它实际上是标准库中的一个类,而不是像 intfloat 这样由编译器处理的特殊类型。就像您的结构一样,string类包含编译器知道大小的字段,因此它知道完整结构的大小,并在使用 new 时使用该大小。

2

new函数将分配sizeof(Airline)所需的空间来存储一个类型为Airline的对象。

对于字符串的管理,string对象保存一些内部数据以管理实际数据存储的内存,但不包括数据本身(除非使用小对象优化)。虽然其他人指出了类似“存储指向实际字符串的指针”的想法,但这并不够精确,因为实现还会存储该指针加上额外的数据,例如size()capacity()(在引用计数实现中还有引用计数等其他数据)。


1

字符串的内存可能在类string内,也可能不在。很可能(甚至很大概率),类string会管理自己的内存,只需使用指向存储数据所用内存的指针即可。例如:

struct Airlane {
    String Name {
        char *data;  // size = 4
        size_t size; // size = 4
    }
    int diameter; // size = 4
    int weight;   // size = 4
}; // size = 16

请注意,这些不一定是实际大小,它们只是为了举例。
另请注意,在C ++中(与例如C不同),对于每个,是一个编译时常量,意味着对象永远不可能具有动态大小。这实际上意味着:一旦需要运行时动态大小的数据,就必须有外部(相对于对象)的内存区域。这可能意味着使用标准容器,例如或,甚至手动管理资源。
这反过来意味着,不需要递归地知道所有成员的动态大小,而只需要知道最外层类的大小,即您分配的类。当此外部类需要更多内存时,它必须自行管理。一些示例p-code:
Airline* myPlane = new Airline {
    Name = {
        data = new char[some-size]
        ...
    }
    ...
}

内部分配由持有构造函数完成:

Airline::Airline() : string(), ... {}
string::string () : data(new char[...] ... {}

operator new除了分配一些固定大小的内存作为Airline的"土壤"(见第一个p-code)之外,什么也不做,然后通过调用字符串构造函数(隐式或显式地),“种植”Airline的构造函数,该构造函数本身必须在那个受限制的“土壤”容量中管理其生存期,这样它就会进行另一个new


0

当你分配Airline时,new会在堆上分配足够的空间来存储两个整数、string及其字段。

string在堆栈上的大小始终相同。但在内部,string存储指向字符数组的指针。


你可能想要添加 where new 分配内存以及 new 返回值与该位置的关系。 - Andrew White

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接