2012-03-05 3 views
7

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

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

Airline* myPlane = new Airline; 

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

Благодаря

+0

Мое предположение, не зная C++, заключается в том, что он хранит только указатель на строку, фактическое содержимое которой находится где-то в куче. –

ответ

12

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

class string 
{ 
    char *buffer; 
    size_t nchars; 

    public: 
    // interface 
}; 

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

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

+0

Спасибо. Это очищает его. – Dan

0

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

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

+0

Возможно, вы захотите добавить * где * new выделяет и как возврат нового относится к этому местоположению. –

0

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

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

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

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

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

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

2

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

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

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

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

2

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

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

+0

блестящий информация. Большое спасибо. – Dan

Смежные вопросы