2015-04-15 6 views
0

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

Моя проблема проста: я читаю что, когда переменная создается с использованием ключевого слова new, ее область действия не ограничена окружающим {..}. Так почему же этот код не компилируется?

{ 
std::string * s = new std::string("foo"); 
} 

std::cout << "print : " << (*s) << std::endl; 

Визуальная Sudio говорит мне: «идентификатор„s“не определен» Таким образом, сфера по-прежнему ограничен с ключевым словом «новый»?

+1

'new' не имеет ничего общего с областью действия переменной.Он выделяет память в кучу, вот и все. –

+0

thx все для точности. Поэтому, если я перефразирую свой вопрос: есть ли способ получить доступ к переменной вне ее диапазона декларации? – Arcyno

+1

@Arcyno: Это совсем другой вопрос. Вы можете получить доступ к любому объекту в течение его жизни, по имени, если это переменная в области видимости или через ссылку или указатель. –

ответ

8

Вы путаете два разных понятия: областей действия имени и прижизненных объекта. Вы также смешиваете два отдельных объекта: переменную указателя s и объект типа std::string, на который указывает.

new std::string создает объект с динамическим временем жизни, который длится до тех пор, пока вы его не удалите. Доступ к нему можно получить из любого места, если у вас есть указатель или ссылка на него. У него нет имени, поэтому в нем нет сферы охвата.

std::string * s объявляет переменную с блоком области действия и автоматической жизни. Имя доступно только в пределах этой области, и переменная (указатель, а не какой-либо объект, на который она указывает) уничтожается, когда программа покидает эту область.

0

Некоторое замешательство здесь: new std::string("foo");выделяет некоторую память и с благодарностью возвращает адрес этого распределения.

Написание std::string * s = ... позволяет сохранить его, чтобы вы могли delete в дальнейшем.

Но как только вы пройдете мимо закрывающей скобки, у вас больше нет такого адреса, поскольку s выйдет за пределы области действия. Но память останется выделенной.

В результате у вас будет утечка памяти, так как у вас не будет никакого delete памяти, которую вы выделили.

1

Объем s ограничен окружающим {}. Строка все еще существует в памяти, но вы потеряли указатель на нее. Утечка памяти.

1

Лексическая область переменной/указателя и область ее памяти - это две разные вещи. Здесь s нельзя ссылаться вне блока объявления. Тем не менее, память, которую он занимает, пока вы не удалите ее, можно решить.

0

Майк уже ответил на этот вопрос, но для того, чтобы получить доступ к памяти позже вы можете сделать это (продолжающуюся свой надуманный пример)

std::string *s; 
{ 
    s = new std::string("Hello, World"); 
} 
std::cout << *s << std::endl; 

Хорошая вещь о указателей является то, что декларация указателя не называть default конструктор std::string, и когда вы используете new, он вызывает конструктор std::string и возвращает указатель обратно в память в куче, где он был построен.

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