2013-06-16 2 views
1

У меня есть следующий кодЛокальная переменная структура не получает уничтожены после возвращения из метода

#include <iostream> 

struct mystruct 
{ 
    float x; 
}; 

void fun(mystruct* ptr) 
{ 
    mystruct str = {10}; 
    ptr = &str; 
    std::cout<<"bbq"; 
} 

class cls 
{ 
public: 
    mystruct* ptr; 
    void fun() 
    { 
     mystruct str = {10}; 
     ptr = &str; 
     std::cout<<"bbq"; 
    } 
}; 

int main() 
{ 
    mystruct* ptr = new mystruct; 
    fun(ptr); 
    std::cout<<"bbq"; 

    cls obj; 
    obj.fun(); 
    std::cout<<"bbq"; 

} 

На первый указатель PTR установлен в функции забавой адрес локальной структуры. Когда функция возвращает локальную структуру, она разрушается, как ожидалось.

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

+0

«Не уничтожаются ли локальные переменные метода после возврата метода?» Да, они. – juanchopanza

+3

[undefined behavior] (http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope) – chris

+1

Что вы видите и что вы ожидаете увидеть ? –

ответ

3

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

void fun(mystruct*& ptr); 

Локальные переменные являются уничтожены после того, как функция возвращает. Но даже после того, как вы увидите значение внутри указателя, установленного на локальную переменную, вы не можете предположить, что локальная переменная была не уничтожена. Если вы разыщите указатель в любое время после присвоения ему истекшему объекту, ваша программа затем имеет неопределенное поведение.

Похожие: Can a local variable's memory be accessed outside its scope?

1

код довольно странно. Например, в этой функции:

void fun(mystruct* ptr) 
{ 
    mystruct str = {10}; // create a structure 
    ptr = &str; // make ptr point to it 
    std::cout<<"bbq"; 
} 

ptr создается к чему-то, но тогда он никогда не используется. ptr передается по значению, поэтому он не может иметь эффекта вне этой функции.

И здесь:

class cls 
{ 
public: 
    mystruct* ptr; 
    void fun() 
    { 
     mystruct str = {10}; // create local variable 
     ptr = &str; // make ptr point to it 
     std::cout<<"bbq"; 
    } 
}; 

Вы устанавливаете класс члена ptr, чтобы указать на локальную переменную, а затем эта переменная уничтожается, когда функция возвращает, поэтому ptr остается указывая на мусор. ptr не используется снова в вашем примере, поэтому никакого вреда не было, но это все еще странно.

И в главном:

int main() 
{ 
    mystruct* ptr = new mystruct; // make ptr point do a dynamically allocated object. 
    fun(ptr); // call fun with a copy of the pointer 
    std::cout<<"bbq"; 

    cls obj; 
    obj.fun(); 
    std::cout<<"bbq"; 
    // That object that ptr is pointing to is never deleted. 

} 

Там нет никакого особого вреда не удаляя то, что вам выделено в этом случае, так как это конец вашей программы, но это хорошая практика, чтобы удалить ваш динамически выделяется объектов в целом.

1

Мы могли бы вызвать неудачу, делая это:

struct mystruct 
{ 
    float x; 
    ~mystruct() { x = 99; } 
}; 


class cls 
{ 
public: 
    mystruct* ptr; 
    void fun() 
    { 
     mystruct str = {10}; 
     ptr = &str; 
     std::cout<<"bbq"; 
    } 
    void fun2() 
    { 
     std::cout << ptr->x << std::endl; 
    } 
}; 

... 
    obj.fun(); 
    obj.fun2(); 

Теперь, может случиться так, что obj.fun2(); печатает 99, или она может показать некоторый случайный другой номер, или это может произойти сбой. Это связано с тем, что «использование объекта, который был уничтожен, является неопределенным поведением» - неопределенное поведение означает, что стандарт C++ не определяет, что происходит, и «что-либо может случиться», включая сбой или зависание, или работает «, как вы ожидаете ». Но объект будет уничтожен.Поскольку исходный код фактически не использует USE ptr после того, как объект, на который он указывает, был уничтожен, ничего плохого не происходит (на самом деле, это даже не неопределенное поведение в примере кода - только неопределено «использовать заостренный объект после того, как объект были уничтожены ").

Edit:

этот код, однако:

mystruct* ptr = new mystruct; 
fun(ptr); 
std::cout<<"bbq"; 

вызывает утечку памяти, поскольку ptr никогда не удаляется (и если fun, где на самом деле изменить ptr вне самой функции, например, с помощью mystruct *&ptr, тогда у вас будет блок памяти для mystruct, который больше не ссылается, что является еще более плотной утечкой памяти - и, конечно же, значение в ptr указывает на уничтоженный объект, поэтому вы не можете использовать ptr)

+0

@BenVoigt: Да, отредактировал формулировку. –

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