문제

While writing on my CFD-Code I had a problem with a vector of pointer. I broke it down to the following code, which represents the core problem:

#include <iostream>
#include <vector>
#include <memory>

class MyClass{
    public:
        MyClass()                               {}
        MyClass(int i)                          {_myVec.push_back(i);}
        ~MyClass()                              {_myVec.clear();}
        const std::vector<int> myVec() const    {return _myVec;}
        std::vector<int> _myVec;
    private:
};


int main(){
    std::size_t size = 3;
    std::vector< std::shared_ptr<MyClass> > myClass;
    // add some elements with push_back
    for(auto i = 0; i < size; i++){
        myClass.push_back(std::shared_ptr<MyClass>(new MyClass()));
    }
    for(auto i = 0; i < size; i++){
        myClass[i]->_myVec.push_back(i);
    }
    // print
    for(auto i = 0; i < size; i++){
        for(auto j = 0; j < myClass[i]->myVec().size(); j++){
            std::cout << myClass[i]->myVec()[j] << " ";
        }
        std::cout << std::endl;
    }
    std::cout << std::endl;
    myClass.clear();


    // add some elements with resize
    myClass.resize(size, std::shared_ptr<MyClass>(new MyClass()));
    for(auto i = 0; i < size; i++){
        myClass[i]->_myVec.push_back(i);
    }
    //print 
    for(auto i = 0; i < size; i++){
        for(auto j = 0; j < myClass[i]->myVec().size(); j++){
            std::cout << myClass[i]->myVec()[j] << " ";
        }
        std::cout << std::endl;
    }
    myClass.clear();
}

The ouput for this piece of code is the following.

0
1
2

0 1 2
0 1 2
0 1 2

The first part is just what I expect. The second part was, what surprised me. The resize function obviously first builds the class and than referes all pointers in the vector to this one class instead of what I thought the vector::resize would do, namely calling the new operator for every element, so that every element in vector would point to its own object. I don't really find this behaviour intuitive and logical, if I wanted to have the same pointer on every vector element, I would tell the compiler so by writing like this:

std::shared_ptr<MyClass> myTempclass = std::shared_ptr<MyClass>(new MyClass())
for(auto i = 0; i < size; i++){
    myClass.push_back(myTempclass);
}

Could somebody please explain why the vector behaves like that in this particular situation, or has a link to a good site (the c++ reference sites didn't help me to explain it)?

도움이 되었습니까?

해결책

The resize function obviously first builds the class and than referes all pointers in the vector to this one class

Actually no, that's not quite what happened. You built the class (and shared pointer) when you wrote std::shared_ptr<MyClass>(new MyClass()) in the call. resize just takes the resulting parameter and does its logic with that.

resize's logic is to create any necessary new values by copying the parameter. Copying a shared_ptr creates new pointer objects which point to the same thing. So that leads to the result you see.

It's as if you had written:

std::shared_ptr<MyClass> ptr(new MyClass());
for(auto i = 0; i < size; i++)
{
    myClass.push_back(ptr);
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top