2015-05-27 3 views
0

Я просто немного обдумываю отражение, и я вижу то, что для меня не имеет смысла. Приложение в значительной степени просит вас ввести имя класса, и если оно обнаружит его на карте, оно создаст экземпляр этого класса и выведет адрес объекта.C++ - Указатели и адреса

В первый раз, когда я набираю Derived1, он генерирует 1 адрес, например (0x00001), во второй раз, когда я печатаю то же имя, он показывает другой адрес (0x00002), а третий раз он снова использует тот же адрес.

Почему я получаю только новый адрес для второго объекта, а не для остальных объектов?

Это отнюдь не проблема, мне просто интересно.

#include <iostream> 
#include <memory> 
#include <map> 
#include <string> 
#include <vector> 
#include <typeinfo> 

class Base 
{ 
protected: 
    int id; 
public: 
    Base(int _id) 
     :id(_id) 
    { 
     std::cout << "Im the base class, and this is my address: " << this << std::endl; 
    } 
    virtual void PrintMyAddress() const = 0; 
    void PrintId() 
    { 
     std::cout << "This is my ID: " << this->id << std::endl; 
    } 
    virtual ~Base(){} 
}; 

class Derived1 : public Base 
{ 
public: 
    Derived1(int _id) : Base(_id){} 
    void PrintMyAddress() const override 
    { 
     std::cout << "I'm derived 1, this is my address: " << this << std::endl; 
    } 
    ~Derived1(){} 
}; 

class Derived2 : public Base 
{ 
public: 
    Derived2(int _id) : Base(_id){} 
    virtual void PrintMyAddress() const override 
    { 
     std::cout << "I'm derived 2, this is my address: " << this << std::endl; 
    } 

    virtual ~Derived2(){} 
}; 

class Derived3 : public Derived2 
{ 
public: 
    Derived3(int _id) : Derived2(_id){} 
    void PrintMyAddress() const override 
    { 
     std::cout << "I'm derived 3, this is my address: " << this << std::endl; 
    } 

    ~Derived3(){} 
}; 

class Generate 
{ 
private: 
    typedef std::unique_ptr<Base> (Generate::*SomeFunction)(int); 
    std::map<std::string, SomeFunction> listFunction; 

public: 
    Generate() 
    { 
     this->MapClasses(); 
    } 

    template <typename T> 
    std::unique_ptr<Base> CreateDerived(int _id) 
    { 
     std::unique_ptr<Base> tmp(new T(_id)); 
     return std::move(tmp); 
    } 

    void MapClasses() 
    { 
     this->listFunction["Derived1"] = &Generate::CreateDerived<Derived1>; 
     this->listFunction["Derived2"] = &Generate::CreateDerived<Derived2>; 
     this->listFunction["Derived3"] = &Generate::CreateDerived<Derived3>; 
    } 

    std::unique_ptr<Base> Class(std::string _name) 
    { 
     if (this->listFunction.find(_name) != this->listFunction.end()) 
     { 
      return std::move((this->*this->listFunction[_name])(rand() % 100)); 
     } 
     else 
     { 
      std::unique_ptr<Base> itsnull; 
      return std::move(itsnull); 
     } 
    } 

    std::map<std::string, SomeFunction>& GetFunctionList() 
    { 
     return this->listFunction; 
    } 
}; 


int main() 
{ 
    Generate gen; 
    bool run = true; 
    while (run) 
    { 
     std::cout << std::endl << "What class do you want to generate? Type in the name of the class: " << std::endl << std::endl; 
     std::string className; 
     std::cin >> className; 
     if (className == "exit") 
     { 
      run = false; 
      continue; 
     } 

     auto genclass = gen.Class(className); 
     if (genclass.get()) 
     { 
      genclass->PrintMyAddress(); 
      genclass->PrintId(); 
      std::cout << "This is my TypeID: " << typeid(*genclass).name() << std::endl; 
     } 
     else 
     { 
      std::cout << "Class couldn't be created because it doesn't exist..." << std::endl; 
     } 
    } 

    std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n'); 
    return 0; 
} 

Это аналогичный пример, но всегда показывает тот же адрес:

for (int i = 0; i < 10; ++i) 
{ 
    int* test = new int; 
    std::cout << test << std::endl; 
    delete test; 
} 

ли компилятор оптимизировать все после второго творения?

+0

Почему вы не изменить ваш 'главный()' так, чтобы она не зависит от какого-либо ввода, который мы не видим? – juanchopanza

+0

Какой вклад? Это весь код. –

+0

Этот вход: 'std :: cin >> className;'. – juanchopanza

ответ

1

Ваш код в основном создавал новый объект, а затем удалял его каждый цикл.

Адрес объекта зависит от того, где его кладет. Куча свободна в повторном использовании пространства, которое недавно было бесплатным (и было бы глупо, если бы это не так), и поэтому вы, скорее всего, получите повторный адрес.

+0

Я обновил свой код, я думаю, его компилятор, который оптимизирует код после второго раза, когда он создает объект? –

+0

Его вряд ли будет компилятором, который делает что-то здесь - его кучу времени выполнения, которая решает, где размещаются объекты. И это может динамически сделать deecisiong на основе внутренних критериев и, что более важно, другими пользователями кучи между итерациями (std :: cout и консольная подсистема, скорее всего, будут использовать кучу также) –

+0

Так что, я думаю, это может отличаться в зависимости от ОС запускают программу, потому что Quicky просто сказал, что он получает тот же адрес, который запускает программу на linux gcc 4.9.0. Интересно. –

0

Когда я проверяю вам код на Linux с GCC 4.9.0 и попросить Derived1 3 раза я всегда получать один и тот же адрес (0xDEAD пример) Причина заключается в том, что компилятор заменит линию

auto genclass = gen.Class(className); 

по

std::unique_ptr<Base> genclass = gen.Class(className); 

Когда исполнение достигнет конца Wile цикла локальная переменная genclass разрушается
unique_ptr делать свою работу, удалив объект он указывает, которые делают адрес 0xDEAD availa BLE для использования
Следующая итерация создаст новый объект и повторно 0xDEAD адресат, потому что он доступен
В вашем случае механизм выделения памяти за это, возможно, немного отличается и адрес виден только на третьей итерации

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

std::cout << "Delete base whose address is " << this << std::endl; 
+0

его интересный друг, спасибо за ответ –

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