C ++: структура и новое ключевое слово - PullRequest
10 голосов
/ 05 марта 2012

Я новичок в C ++, у меня есть следующий фрагмент кода:

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

Airline* myPlane = new Airline;

Мой вопрос: когда я вызываю метод new, он выделяет память, если я правильно помню.Как ПК узнает, сколько памяти выделить, особенно если учесть, что там есть строковый тип?

Спасибо

Ответы [ 5 ]

13 голосов
/ 05 марта 2012

Объект std::string имеет фиксированный размер; он содержит указатель на фактический буфер символов вместе с его длиной. std::string определение выглядит примерно так

class string
{
    char *buffer;
    size_t nchars;

  public:
    // interface
};

Следовательно, ваши Airline объекты также имеют фиксированный размер.

Теперь new не только выделяет; он также инициализирует ваш объект, включая std::string, что означает, что он, вероятно, устанавливает указатель char на 0, поскольку строка пуста.

3 голосов
/ 05 марта 2012

Вы также можете получить размер структуры, используя sizeof:

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

Это потому, что компилятор знает поля внутри структуры и суммирует размеры каждого члена структуры.

Объект string ничем не отличается от вашей структуры. На самом деле это класс в стандартной библиотеке, а не специальный тип, такой как int или float, который обрабатывается компилятором. Как и ваша структура, класс string содержит поля, размер которых компилятор знает, и поэтому он знает размер вашей полной структуры и использует его при использовании new.

2 голосов
/ 05 марта 2012

При вызове new будет выделено sizeof(Airline), что необходимо для хранения объекта типа Airline.

Что касается управления строками, объект string содержит некоторые внутренние данные для управления памятью фактических сохраненных данных, но не сами данные (если не используется оптимизация небольших объектов). Хотя идея та же самая, что указывалось другими при , в ней хранится указатель на фактическую строку , что недостаточно точно, поскольку ее реализации будут хранить этот указатель плюс дополнительные данные, необходимые для хранения size(). и capacity() (и другие, подобные подсчету ссылок в реализациях подсчета ссылок).

1 голос
/ 05 марта 2012

Память для строки может или не может быть в пределах класса 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, например), для каждого class T, sizeof T - постоянная времени компиляции, означающая, что объекты никогда не могут иметь динамический размер.Это по сути означает: как только вам понадобятся данные динамического размера во время выполнения, должны появиться области внешней (по отношению к объекту) памяти.Это может подразумевать использование стандартных контейнеров, таких как std::string или std::vector, или даже ресурсов, управляемых вручную.

Это, в свою очередь, означает, что operator new не нужно рекурсивно знать динамический размер всех членов, но только размер внешнего класса, который вы выделяете.Когда этому внешнему классу нужно больше памяти, он должен управлять им сам.Примерный p-код:

Airline* myPlane = new Airline {
    Name = {
        data = new char[some-size]
        ...
    }
    ...
}

Внутренние выделения выполняются удерживающими конструкторами:

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

operator new не делает ничего другого, кроме как выделение некоторой памяти фиксированного размера как "грунт "для Airline (см. первый p-код), а затем" конструктор "Airline семени, который сам должен управлять своим временем жизни в этом ограниченном объеме" грунта ", вызывая конструктор строки (неявно или явно), который сам делает еще один new.

0 голосов
/ 05 марта 2012

Когда вы выделяете Airline, new выделит достаточно места в куче для двух целых чисел, string и его полей.

A string всегда будет одинакового размера в стеке. Однако внутри string хранит указатель на массив символов.

...