繁体   English   中英

emplace_back当同一列表循环时

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM