两个对象似乎共享相同的地址

时间:2013-10-11 16:14:39

标签: c++ visual-studio templates

我正在使用Visual Studio Ultimate 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分配不同的地址。

2 个答案:

答案 0 :(得分:4)

第二个push_back / PushOne导致您std::vector<A>重新分配以重新分配,以便现在第一个A元素不再位于00700350

您的Later addresses打印输出确认了这一点。

答案 1 :(得分:3)

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