2012-01-08 3 views
1

Я начал с Java, поэтому я немного запутался о том, что происходит с стек/кучу на следующей строке:Указатели на объекты в C++ - что на стеке/куче?

string *x = new string("Hello"); 

где x является локальной переменной. В C++ все-таки случается ли что-нибудь в стеке относительно этого утверждения? Я знаю, что из чтения он говорит, что объект находится в куче, но как насчет x? В Java x будет в стеке, просто удерживая адрес памяти, указывающий на объект, но я не нашел ясного источника, который говорит, что происходит на C++.

+2

Зависит. Является ли 'x' локальной переменной? –

+0

Да, это локально. Я должен был упомянуть об этом. Будем добавлять его, спасибо. – id2341677

+0

Возможно, [этот мой ответ] (http://stackoverflow.com/a/7462893/596781) представляет интерес, или [этот] (http://stackoverflow.com/a/7581238/596781), или [this one] (http://stackoverflow.com/a/8439947/596781), или [этот] (http://stackoverflow.com/a/6816851/596781), или [этот] (http://stackoverflow.com/a/7620541/596781). –

ответ

3

Любой объект, который вы только что создали, например. x в вашем примере находится в стеке. Объект x - это всего лишь указатель, который указывает на кучу, выделенную string, которую вы положили в кучу, используя new string("Hello"). Как правило, вы не создавали бы такую ​​строку на C++. Вместо этого вы будете использовать

string x("Hello"); 

Это будет по-прежнему выделять x в стеке. Являются ли символы, представляющие значение x, также живут в стеке или, скорее, в куче, зависят от реализации string. В качестве разумной модели вы должны предположить, что они находятся в куче (некоторая реализация std::string помещает короткую строку в объект стека, избегая распределения кучи и помогая с локальностью).

2

Да, x находится в стеке: это локальная переменная, находящаяся в стеке.

Оператор new провоцирует выделение памяти на кучу.

+1

Иш. Термины C++ являются «автоматическими» и «динамическими», что обычно соответствует стеку и куче соответственно. –

+0

Нет такой вещи, как «новый оператор», и есть много вещей, которые могут так или иначе включать слово «новое» и делать совершенно разные вещи. –

+0

Недостаточно кода, чтобы узнать, является ли 'x' локальным или нет. –

2

Это то же самое, что и на Java. string или String находится в куче, а указатель (или ссылка в Java) находится в стеке.

В Java все объекты находятся в куче, а стек состоит только из примитивных типов и самих ссылок. (У стека есть другие вещи, такие как обратные адреса и т. Д., Но неважно, что).

Основное отличие между стеком C++ и стекю Java состоит в том, что на C++ вы можете поместить весь объект непосредственно в стек. например string x = string("Hello");

В C++ также возможно нанести примитивные типы непосредственно на кучу. например int * x = new int();. (Другими словами, «если автобоксирование является решением, то в чем проблема?»)

Вкратце, Java имеет жесткие различия между примитивными типами и объектами, а примитивы очень во втором классе. C++ гораздо более расслаблен.

+1

Нет гарантии, что указатель находится в стеке. Они также могут быть встроены в другие объекты (не допускаемые этим конкретным синтаксисом), локали со статической продолжительностью или глобальными. –

+0

Все хорошие моменты, @BenVoigt. Но в этом конкретном примере «string * x = new string (« Hello »);' не гарантируется ли это локальная переменная в стеке? (За исключением, возможно, для этой новой вещи C++ 11, где я думаю, что члены данных структуры могут быть объявлены и определены следующим образом.) –

+0

Это мог быть глобальный (или элемент пространства имен), пока вопрос не был отредактирован, чтобы сказать локальный. Но я хочу предотвратить удивительно распространенное недоразумение среди программистов на Java и .NET, что «объекты идут в кучу, примитивы и ссылки идут в стек», который полностью игнорирует членов других объектов. –

0

Это зависит от того, где находится эта линия. Если он находится где-то в области файла (т. Е. Вне функции), то x - это глобальная переменная, которая определенно равна , а не в стеке (ну, теоретически это можно было бы положить в стек перед вызовом main(), но я сильно сомневаюсь, что любой компилятор делает это), но также не в куче. Если, однако, строка является частью функции, то действительно x находится в стеке.

С x имеет тип string* (то есть указатель на строку), он действительно содержит только адрес строкового объекта, выделенного new.Поскольку этот строковый объект выделен new, он действительно живет в куче.

Обратите внимание, что, в отличие от Java, нет необходимости, чтобы встроенные типы находились в стеке и объекты класса, находящиеся в куче. Ниже приведен пример указателя, живущего на куче, указывающего на объект, живущий в штабеле:

int main() 
{ 
    std::string str("Hello"); // a string object on the stack 
    std::string** ptr = new std::string*(&str); // a pointer to string living on the heap, pointing to str 
    (**ptr) += " world"; // this adds "world" to the string on the stack 
    delete ptr; // get rid of the pointer on the heap 
    std::cout << str << std::endl; // prints "Hello world" 
} // the compiler automatically destroys str here 
+0

Думаю, вам не хватает пары звездочек. –

+0

@BenVoigt: Ой, да, спасибо, я добавил их сейчас. – celtschk

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