【问题标题】:c++ list not resizing after set differencec ++列表在设置差异后未调整大小
【发布时间】:2021-09-13 22:45:53
【问题描述】:

考虑以下代码:

#include <algorithm>
#include <iostream>
#include <list>

int main() {
    std::list<int> v = {1, 3, 4};
    std::cout << v.size() << std::endl;
    v.resize(0);
    std::cout << v.size() << std::endl;
}

按预期编译输出后是

3
0

现在我添加一组差异。

#include <algorithm>
#include <iostream>
#include <list>

int main() {
    std::list<int> x = {1, 3, 4};
    std::list<int> y = {1, 2, 3, 5};
    std::list<int> v;
    x.sort();
    y.sort();
    std::cout << v.size() << std::endl;
    auto it =
        std::set_difference(x.begin(), x.end(), y.begin(), y.end(), v.begin());
    std::cout << v.size() << std::endl;
    v.resize(0);
    std::cout << v.size() << std::endl;
}

输出是

0
4
4

为什么第一个示例的调整大小有效,而第二个示例无效?

【问题讨论】:

    标签: c++ set-difference


    【解决方案1】:

    这是因为它是未定义的行为。

    std::set_difference 的最后一个参数是输出迭代器。你传入v.begin()

    这将返回一个指向空列表开头的指针。为了使您的预期代码能够像宣传的那样工作,输出迭代器的*iter++ 操作必须将新值添加到列表中

    不幸的是,无论您对begin() 返回的迭代器做什么,您对它所做的任何操作都不会使列表变得比现在更大或更小。它只是迭代列表的现有内容

    此时,您几乎处于未定义的行为领域,您得到的任何结果都将是完全荒谬的(如果不是立即崩溃的话)。

    您需要use std::back_insert_iterator instead,而不是传递v.begin()

    【讨论】:

    • std::back_inserter 简化了使用std::back_insert_iterator。您可以将v.begin() 替换为std::back_inserter(v)
    • @Sam 解释的很好,另外如果你不想使用 back_insert_iterator,你可以在初始化时给出v 的大小,最大可以是 x 的大小,所以为了安全起见,您可以将其初始化为 std::list&lt;int&gt; v(x.size());,尽管这很浪费内存。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-10
    • 2013-04-18
    相关资源
    最近更新 更多