2015-01-15 3 views
0

Я знаю, что этот вопрос был задан много в SO, как в Object creation on the stack/heap? Насколько я понимаю, если объект хранится в Stack, он будет всплывать, если переменная выходит из области видимости. Но когда дело доходит до автоматического хранилища, это путает меня, как это не в куче. Я читал, что использование нового и удаления на C++ не рекомендуется (или даже зло - это выбор слова), потому что это приведет к утечке памяти. Так что устройство тестовый код как этиОбъект C++ хранится в стеке или куче

#include <iostream> 
#include <string> 

class Cat 
{ 
public: 
    Cat(const std::string& name) 
    { 
     this->name = name; 
     std::cout << "construct Cat " << this->name << std::endl; 
    } 
    ~Cat() 
    { 
     std::cout << "destruct Cat " << this->name << std::endl; 
    } 
    void feed() 
    { 
     std::cout << "feed Cat " << this->name << std::endl; 
    } 
private: 
    std::string name; 
}; 

Cat createFelix() 
{ 
    Cat garfield("Garfield"); 
    Cat felix("Felix"); 
    garfield.feed(); 
    felix.feed(); 
    return felix; 
} 

void getAndFeedFelix() 
{ 
    Cat justFelix = createFelix(); 
    justFelix.feed(); 
} 

int main() 
{ 
    getAndFeedFelix(); 
    std::cout << "bla bla blah" << std::endl; 
} 

и это привело, как эти

construct Cat Garfield 
construct Cat Felix 
feed Cat Garfield 
feed Cat Felix 
destruct Cat Garfield 
feed Cat Felix 
destruct Cat Felix 
bla bla blah 

так в моем заключении, функция createFelix() вызывается из getAndFeedFelix(), который возвратил Cat (который, хранящийся в стеке), который должен выскочить из стека после возвращения функции, но объект разрушен после того, как getAndFeedFelix() вышел из сферы действия, из-за автоматического хранения меканизма. Как это может произойти? Если автоматическое хранилище использует кучу и подсчет ссылок, тогда это возможно. Неправильно ли моя логика?

+0

Автоматическое хранилище использует стек, а не кучу – vsoftco

+3

. Если вы хотите просмотреть все детали, вам необходимо реализовать инструментарий копирования и оператор присваивания. –

+2

«Я читал, что использование нового и удаления на C++ не рекомендуется (или даже зло - это выбор слова), потому что это приведет к утечке памяти». Тот, кто сказал, что не работал над реальным проектом. –

ответ

4

Вы обнаружили Return Value Optimization (в частности, названную оптимизацию значения).

Эта функция:

Cat createFelix() 
{ 
    Cat felix("Felix"); 
    return felix; 
} 

Cat justFelix = createFelix(); 

выглядит, как он должен создать Cat, скопируйте его, и уничтожить его. Но в качестве оптимизации createFelix() фактически создает felix в памяти, принадлежащей justFelix. Поэтому мы просто создаем один Cat с нулевыми копиями. Все здесь находится в стеке.

Итак:

void getAndFeedFelix() 
{ 
    Cat justFelix = createFelix(); // creates a cat 
    justFelix.feed();    // feeds a cat 
}         // destroys a cat 

Какой выход вы видите.

+0

Как тогда вы тестируете функцию 'createFelix()', поэтому объект 'felix' хранится в стеке? Я воздерживаюсь от использования 'return Cat (« felix »);' непосредственно, чтобы избежать этой оптимизации. –

+0

@MarcelDaryanto. Почему вам нужно проверить, живет ли что-то в стеке? Он гарантирован на 100%, так что тест не требуется. –

+0

Потому что, как я понимаю, если объект, живущий в стеке, будет освобожден после выхода из области, в вызове функции после оператора возврата весь выбранный стек будет поп. Поэтому, если вы хотите получить доступ к объекту для использования позже, он не будет доступен, CMIIW. Но если он использует интеллектуальный указатель, такой как автоматический подсчет ссылок и хранится в куче, он не будет освобожден до тех пор, пока что-то ссылается на него. –

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