Я использую 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
назначаются разные адреса.
Второй push_back/PushOne приводит к перераспределению на вашем std::vector<A>
чтобы увеличить его, так что теперь первый элемент A больше не находится в 00700350
.
Распечатка вашего более Later addresses
подтверждает это.
Когда вы нажимаете элементы на вектор, в конечном итоге ему нужно будет выделить новую память и освободить старую память (которую могут использовать другие распределения). Итак, по-видимому, когда вы отодвинули второй раз для Container<A>
, произошло перераспределение. Затем, когда вы нажимаете Container<B>
, его вектор использовал память, которую выпустил другой вектор (Container<A>
). Это прекрасно.