2013-10-11 50 views
0

我使用Visual Studio旗舰2013预览,Windows 7的两个对象似乎共享相同的地址

我使用CRTP能够方便地将任何类型的对象到一个单独的载体。

但是结果很奇怪。你会看到我有两个类,AB,它们来自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 

正如你可以看到,第一个和最后一个条目(其分别存储在变量ab )首先打印相同的地址。

当我第二次打印地址时,第一次得到不同的结果A *。

我总是得到相同的结果,除非我注释掉行auto b = ...。如果我这样做,ab被分配不同的地址。

+0

@ Matthias247猜猜你是对的,如果我在使用前“保留”,问题就会消失,以防止重新分配。如果您希望我接受它,请给出答案。先到先得 ;) – s3rius

回答

4

第二个push_back/PushOne会导致在您的std::vector<A>上重新分配以使其增长,因此现在第一个A元素不再位于00700350处。

您的Later addresses打印输出确认此消息。

3

当您将元素推送到矢量上时,最终需要分配新内存并释放旧内存(其他分配可能使用)。所以,显然,当你第二次推回Container<A>时,发生了重新分配。然后,当你按下Container<B>时,它的向量使用其他向量(Container<A>)发布的内存。这是完全正确的。

相关问题