2013-10-11 94 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>)發佈的內存。這是完全正確的。

相關問題