C++ 在后台STL:将std::vector连接到自身,而不使用新的vector

C++ 在后台STL:将std::vector连接到自身,而不使用新的vector,c++,stl,vector,C++,Stl,Vector,我有一个存储矩阵对角线的STL向量。我正在实现的某个数学规则告诉我,我可以生成一个张量积对角线的新矩阵,只需获取原始向量并将该向量的副本连接到它本身(它的大小加倍,值在1/2*size()之后重复) 我编写了以下代码: std::vector<int> aVec; for (int k = 0; k < aVec.size(); k++) aVec.insert(aVec.end(), aVec[k]); std::vector aVec; 对于(intk=0;k开始/

我有一个存储矩阵对角线的STL向量。我正在实现的某个数学规则告诉我,我可以生成一个张量积对角线的新矩阵,只需获取原始向量并将该向量的副本连接到它本身(它的大小加倍,值在1/2*size()之后重复)

我编写了以下代码:

std::vector<int> aVec;

for (int k = 0; k < aVec.size(); k++) aVec.insert(aVec.end(), aVec[k]);
std::vector aVec;
对于(intk=0;k
但当我尝试这个时,我会遇到seg故障。如果我创建一个aVec副本,并将其用作插入“值”,以及将其用于循环参数中的size(),它将起作用,但我必须同时执行这两项操作(否则我仍然会出现seg错误)


有人能解释一下下面发生了什么导致此实现无法工作吗?

在开始向aVec添加元素之前,您应该先阅读一次aVec.size()的值

您将无限期地复制项目。请注意要提前复制的数量:

size_t n = aVec.size();
for (int k = 0; k != n; ++k)
  aVec.push_back(aVec[k]);
虽然许多C++算法使用<>代码>开始/ <代码> >代码> >(或)>代码迭代器,但在这种情况下,通过索引访问是优越的,因为修改容器可能会使迭代器无效,但是元素访问将保持有效。但是,您可以使用
reserve
来避免无效:

aVec.reserve(2*aVec.size());
std::copy(aVec.begin(), aVec.end(), std::back_inserter(aVec));

使用基于迭代器的操作:

vec.reserve(vec.size() * 2);
vec.insert(vec.end(), vec.begin(), vec.end());

连接两个向量有一个很好的方法。你确定在插入之前需要
保留
insert
的复杂度必须是
线性的,即插入的元素数加上到向量末端的距离。如果我理解正确,这意味着需要一个
insert
的实现来计算两个输入迭代器之间的距离,并为新的元素数保留足够的容量,我错了吗?@Luc但这会使传递给它的迭代器范围无效。嗯,对,我想这项要求涉及的是摊销后的复杂性。尽管如此,我是否正确地认为一些实现将专门针对随机访问迭代器
insert
,以便事先执行保留(即使标准不要求任何此类内容)?@Luc几乎可以肯定。我知道stdlibc++实现是为容器构造函数做的,如果
insert
的行为不同,那就很奇怪了。我希望标准库的其他实现也能做到这一点。您不应该以这种方式追加,它是未定义的行为()。这在某些实现中可能有效,但它仍然是未定义的行为。@BenVoigt:这两种方法中的哪一种?第一个我会考虑范围之内。后者并不完全符合规范:“重新分配会使序列中引用元素的所有引用、指针和迭代器无效。在调用
reserve()后发生的插入期间,不会发生重新分配
直到插入会使向量的大小大于
capacity()
”的值,但是
end()
不是引用元素的迭代器,因此理论上它可能会失效。我想不出任何方法来实现向量,使其失效。重新分配并不是导致失效的唯一操作。任何插入或删除操作都会使插入/删除点处或之后的句柄(迭代器/指针/引用)无效。插入/删除点之前的句柄可以,但是
end()
不在插入点之前。