只保存最后一个元素的std::向量。

问题描述 投票:0回答:1

我已经创建了2个班级。algorithmpeopleEncoding:

  • peopleEncoding 有一个私人属性 _solution 这是个 std::vector 包含整数。
  • algorithm 有一个私有属性 _population 这是个 std::vector 含有指向 solutionEncoding 的实例。

algorithm 类也有一个叫做 initPopulation 充满 _population 像这样。

void initPopulation (unsigned peopleQuantity){
    solutionEncoding * newOne = new solutionEncoding();
    for (unsigned i = 0; i < peopleQuantity; i++ ){
        newOne->generateRandom();
        this->_population.push_back(newOne);
    }
}

如果我打印 _solution 属性来自 peopleEncoding 实例存储在 _population (刚到 push_back 行),我得到了预期的结果,但如果我在循环括号后做,向量就会发生变化(它们都是一样的,等于最后一个推送的)。

我不确定正确使用 new.

c++ new-operator
1个回答
3
投票

问题是

这条线。

this->_population.push_back(newOne);  

推回在最后的 _population 向量 newOne 指向 solutionEnconding. 由于你只初始化了一个指针,所以它是指向同一个对象的同一个指针,而这个对象在所有的 _population 向量。

期望值

当你调用这个成员函数时,

   newOne->generateRandom();

你可能会改变你的一些属性 solutionEncoding 的每一个元素,你似乎期待着。_population 因此,向量是随机的。 但事实并非如此,因为你只有一个对象。

潜在的解决方案

为了达到你想要的目的,你需要在每次迭代中生成一个新的指向不同对象的指针。 只需移动带有 new 到循环中。 但这并不是一个好办法,因为你将不得不进行大量的内存管理(对每一个 new,你需要一个 delete),但有一定的风险(如浅层复制和双重删除)。

因此,一个更安全的方法是将 _population 含有以下内容的向量 solutionEncoding 对象。 newOne 也将是一个 solutionEncoding 对象。 push_back() 每次都会存储一个不同的副本。

std::vector<solutionEncoding> _population; 
...
void initPopulation (unsigned peopleQuantity){
    solutionEncoding newOne{};        // create a new local object - no 'new' needed
    for (unsigned i = 0; i < peopleQuantity; i++ ){
        newOne.generateRandom();        // shuffle all this data :-)
        _population.push_back(newOne);  // store a copy of the current data
    }
}

如果solutionEncoding不是一个多态类的话,这就很好用了。 如果你打算派生出 solutionEncoding 类,这将无法工作,因为切片。 在这种情况下,你会使用一个 shared_ptr:

std::vector<shared_ptr<solutionEncoding>> _population; 
...
void initPopulation (unsigned peopleQuantity){
    for (unsigned i = 0; i < peopleQuantity; i++ ){
        auto newOne = make_shared<solutionEncoding>(); // create a different new object each time
        newOne->generateRandom();       // shuffle all this data :-)
        _population.push_back(newOne);  // store the pointer to the new object
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.