[英]emplace_back when loop of the same list
我向你介绍我的问题
我有2个列表,分别命名为A和B。
list<vector<int> > A = {{1},{2},{3}};
list<vector<int> > B = {{4},{5},{6}};
我想要的是A = {{1,4},{1,5},{1,6},{2,4},{2,5},{2,6},{3,4} ,{3,5},{3,6}},而无需使用任何tmp列表。
我在Ubuntu 12.04上将C ++ 11与gcc 4.6.3一起使用
这样最小化代码:
auto A_begin = A.begin();
auto A_end = A.end();
auto B_begin = B.begin();
auto B_end = B.end();
for(auto i = A_begin; i != A_end; ++i) //loop on A
{
for (auto j = B_begin;j != B_end; ++j) //loop on B
{
vector<int> tmp = (*i); // A[i]
copy((*j).begin(),(*j).end(),back_inserter(tmp)); // append B[j] to A[i]
A.emplace_back(tmp); //add it to A
}
}
A.erase(A_begin,A_end); // remove {1},{2},{3}
因此,我认为该算法还可以,但是它在A上产生了无限循环。我认为当我进行A.emplace_back时,A_end发生了变化,但是我保存了它,所以我真的不知道在这里附加wat。
我的代码来识别问题:
auto A_begin = A.begin();
auto A_end = A.end();
auto B_begin = B.begin();
auto B_end = B.end();
int ii = A.size();
for(auto i = A_begin; i != A_end; ++i) //loop on A
{
for (auto j = B_begin;j != B_end; ++j) //loop on B
{
vector<int> tmp = (*i);
A.emplace_back(tmp);
}
cout<<--ii<<endl; // exit when print 0 ?
}
此打印负数,我又要^ C。
编辑:我找到一个解决方案:
auto A_begin = A.begin();
auto A_end = A.end();
auto B_begin = B.begin();
auto B_end = B.end();
list<vector<int>> tmp_l;
for(auto i = A_begin; i != A_end; ++i) //loop on A
{
for (auto j = B_begin;j != B_end; ++j) //loop on B
{
vector<int> tmp = (*i); // A[i]
copy((*j).begin(),(*j).end(),back_inserter(tmp)); // append B[j] to A[i]
tmp_l.emplace_back(move(tmp)); //add it to A
}
}
swap(tmp_l,A);
这两行:
vector<int> tmp = (*i); // A[i]
copy((*j).begin(),(*j).end(),tmp.end()); // append B[j] to A[i]
将调用未定义的行为。 通过复制到tmp.end(),您仅在A [i]结束后覆盖内存,而不扩展A [i]。 您需要使用back_insert迭代器,例如:
vector<int> tmp = (*i); // A[i]
copy((*j).begin(), (*j).end(), back_inserter(tmp)); // append B[j] to A[i]
您还需要包括标题以获取back_inserter。
编辑:此外,A_end迭代器指向列表的“过去”位置,因此无论您添加到a的项目数是多少,它们总是添加在A_end的前面,因此无限循环。 我不确定是否有解决此问题的好方法。 这里不创建临时列表没有任何好处,您可以通过两种方式分配相同的内存,只需写入新列表即可。
您的算法不好。
这个 :
copy((*j).begin(),(*j).end(),tmp.end());
会导致各种问题,因为您覆盖了一些随机内存。
您可能想要执行以下操作:
vector<int> tmp = (*i);
copy((*j).begin(),(*j).end(),std::back_inserter(tmp));
编辑:我找到一个解决方案:
该解决方案很好,使用临时向量并将其与A
交换比在原位进行替换要好 ,因为您的原始版本(以及复制到向量的末尾)从头开始进行了erase
,从而移动了每个元素。
但是您的解决方案可以改进:
// get rid of these iterators, they're useless
/*
auto A_begin = A.begin();
auto A_end = A.end();
auto B_begin = B.begin();
auto B_end = B.end();
*/
list<vector<int>> tmp_l;
// use new for loops
for (auto& a : A)
{
for (auto& b : B)
{
// use auto
auto tmp = a; // A[i]
// I find just inserting at the end simpler than using `back_inserter`
tmp.insert(tmp.end(), b.begin(), b.end()); // append B[j] to A[i]
// then clear it the moved-from elements:
b.clear();
// move the tmp vector into place, do not copy it.
tmp_l.emplace_back(std::move(tmp));
}
}
swap(tmp_l,A);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.