2013-10-11 2 views
0

Я использую Visual Studio Ultimate 2013 Preview Windows 7.Два объекта, кажется, имеет тот же самый адрес

Я использую CRTP, чтобы иметь возможность удобно толкать объекты любого типа в отдельный вектор.

Результаты довольно странные. Вы увидите, что у меня есть два класса: A и B, которые производятся от Container. С T* PushOne() новый экземпляр вставляется в статический вектор, и его адрес возвращается для использования.

По какой-то причине, первый экземпляр объекта класса A и первый класс B похоже, имеют тот же адрес.

Вот код:

template <typename T> 
class Container{ 
public: 
    static std::vector<T> elements; 

    static T* PushOne(){ 
     //Push a new T object into the vector 
     elements.push_back(T{}); 
     //Print out its address 
     std::cout << "Make " << typeid(T).name() << " at " << &elements[elements.size() - 1] << "\n"; 
     //Return its address. 
     return &elements[elements.size() - 1]; 
    } 
}; 

template <typename T> 
std::vector<T> Container<T>::elements; 

class A : public Container<A>{ 
}; 

class B : public Container<B>{ 
}; 

int main(int argc, char** args){ 
    std::cout << "First addresses:\n"; 

    //a and c are assigned the address 
    auto a = Container<A>::PushOne(); 
    auto b = Container<A>::PushOne(); //Problem gone if this is commented 
    auto c = Container<B>::PushOne(); 

    std::cout << "\nLater addresses:\n"; 
    std::cout << &Container<A>::elements[0] << "\n" 
       << &Container<A>::elements[1] << "\n" 
       << &Container<B>::elements[0] << "\n"; 

    std::cin.get(); 
} 

Выход один из запуска на моей машине:

First addresses: 
Make class A at 00700350 
Make class A at 006FA929 
Make class B at 00700350 

Later addresses: 
006FA928 
006FA929 
00700350 

Как вы можете видеть, первая и последняя запись (которые хранятся в переменных a и b соответственно) сначала напечатайте тот же адрес.

Когда я печатаю адреса во второй раз, у меня получается другой результат для первого A *.

Я всегда получаю тот же результат, если не прокомментировать строку auto b = .... Если я это сделаю, то назначаются разные адреса a и b.

+0

@ Matthias247 Угадайте, что вы правы, проблема исчезает, если я «резервирую» перед использованием, чтобы предотвратить перераспределение. Сделайте ответ, если хотите, чтобы я принял его. Первый пришел первый обслужен ;) – s3rius

ответ

4

Второй push_back/PushOne приводит к перераспределению на вашем std::vector<A>, чтобы увеличить его, так что теперь первый элемент A больше не находится на 00700350.

Ваш Later addresses распечатка подтверждает это.

3

Когда вы нажимаете элементы на вектор, в конце концов, ему нужно будет выделить новую память и освободить старую память (которую могут использовать другие распределения). Итак, по-видимому, когда вы отодвинули второй раз за Container<A>, произошло перераспределение. Затем, когда вы нажали Container<B>, его вектор использовал память, которую выпустил другой вектор (Container<A>). Это прекрасно.

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