矢量副本不起作用,但手动push_back

时间:2014-12-11 16:18:09

标签: c++ stl

我有一种奇怪的行为,这可能是一个初学者的问题:

在类成员函数中,我试图用另一个向量替换给定的向量。

template <typename FITNESS_TYPE>
void BaseManager<FITNESS_TYPE>::replacePopulation (
typename Population<FITNESS_TYPE>::chromosome_container replacementPopulation)
{
    _population.getChromosomes().clear();

   //This inserts the contents of replacementPopulation into _population.getChromosomes()
    for (
          typename Population<FITNESS_TYPE>::chromosome_container::iterator 
          it  = replacementPopulation.begin();
          it != replacementPopulation.end();
          ++it)
          {
             _population.getChromosomes().push_back(*it);
          }


    //But this does nothing...
     std::copy(replacementPopulation.begin(),replacementPopulation.end(), _population.getChromosomes().begin());


     for (typename Population<FITNESS_TYPE>::chromosome_container::iterator it = _population.getChromosomes().begin(); it!=_population.getChromosomes().end(); ++it)
     {
         std::cout << "CHROM: " << **it << std::endl;
     }
}

相应的getChromosomes()getter如下:

template <typename FITNESS_TYPE>
class Population : public printable {
public:
    typedef typename std::vector<Chromosome::BaseChromosome<FITNESS_TYPE>* > chromosome_container;
    typedef typename chromosome_container::const_iterator const_it;
    typedef typename chromosome_container::iterator it;
    const chromosome_container& getChromosomes() const { return _chromosomes; }
    chromosome_container& getChromosomes() { return _chromosomes; }
private:
    chromosome_container _chromosomes;
};
我很困惑。为什么副本不像for循环那样工作?

4 个答案:

答案 0 :(得分:8)

push_back调整向量的大小,而写入begin()以及后面的内容假定空间已经存在。你想要的是这样的:

std::copy(replacementPopulation.begin(),
          replacementPopulation.end  (),
          std::back_inserter(_population.getChromosomes()));

#include <iterator>获取back_inserter

本质上,std::back_inserter是一个迭代器,每次写入内容时都会执行push_back

答案 1 :(得分:4)

copy要求其输出迭代器是有效范围的起点,至少与输入范围一样大。在你的情况下,它是一个空范围的开始;所以copy会将它从向量的末尾递增出来,写入超出的内存,并导致未定义的行为。

这里最简单的解决方案就是重新分配矢量

_population.getChromosomes() = replacementPopulation;

如果确实需要附加到向量而不是替换其所有内容,则可以使用插入迭代器:

std::copy(replacementPopulation.begin(), replacementPopulation.end(),
          std::back_inserter(_population.getChromosomes()));

答案 2 :(得分:3)

vector实际上有一个insert方法,它接受迭代器:

_population.getChromosomes().insert(
    _population.getChromosomes().end(),
    replacementPopulation.begin(),
    replacementPopulation.end());

确保_population.getChromosomes()已正确调整大小,以便您无法运行。根据两个迭代器之间的距离,如果需要,也只会执行一个reserve(),因此这将比提出的std::copy()解决方案更加有效。

或者,如果你真的只是复制矢量:

_population.getChromosomes() = replacementPopulation;

答案 3 :(得分:1)

复制假定目标容器中有复制元素的空间,它将替换它们。您可以使用“back_inserter”创建一个特殊的迭代器,它将插入元素而不是替换,以避免在复制之前调整大小。

std::copy(replacementPopulation.begin(),replacementPopulation.end(), std::back_inserter(_population.getChromosomes()));