在我的CFD代码上编写时,我的指针向量遇到了问题。我将其分解为以下代码,它代表了核心问题:
#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();
}
这段代码的输出如下。
0
1
2
0 1 2
0 1 2
0 1 2
第一部分正是我所期望的。第二部分是,让我感到惊讶。resize 函数显然首先构建类,然后将向量中的所有指针引用到这个类,而不是我认为 vector::resize 会做的事情,即为每个元素调用 new 运算符,以便向量中的每个元素都指向它自己的对象。我真的不觉得这种行为直观和合乎逻辑,如果我想在每个向量元素上都有相同的指针,我会通过这样写来告诉编译器:
std::shared_ptr<MyClass> myTempclass = std::shared_ptr<MyClass>(new MyClass())
for(auto i = 0; i < size; i++){
myClass.push_back(myTempclass);
}
有人可以解释为什么向量在这种特定情况下表现得像这样,或者有一个指向好站点的链接(c++ 参考站点没有帮助我解释它)?
resize 函数显然首先构建类,然后将向量中的所有指针引用到这个类
实际上不,事实并非如此。您在调用中编写std::shared_ptr<MyClass>(new MyClass())
时构建了类(和共享指针)。调整大小仅获取结果参数并执行其逻辑。
Resize 的逻辑是通过复制参数来创建任何必要的新值。复制shared_ptr会创建指向同一事物的新指针对象。所以这导致了你看到的结果。
就好像你写过:
std::shared_ptr<MyClass> ptr(new MyClass());
for(auto i = 0; i < size; i++)
{
myClass.push_back(ptr);
}