为啥在 std::copy 期间使用 std::back_inserter 而不是 end()?

Posted

技术标签:

【中文标题】为啥在 std::copy 期间使用 std::back_inserter 而不是 end()?【英文标题】:Why use std::back_inserter instead of end() during std::copy?为什么在 std::copy 期间使用 std::back_inserter 而不是 end()? 【发布时间】:2019-01-21 20:54:22 【问题描述】:

我见过std::copy() 使用std::back_inserter 但我使用std::end() 并且两者都有效。我的问题是,如果std::end() 工作正常,为什么还需要std::back_inserter

#include <iostream> 
#include <iterator> 
#include <vector> 
#include <algorithm> 
using namespace std; 

int main() 
 
    // Declaring first container 
    vector<int> v1 =  1, 2, 3 ; 

    // Declaring second container for 
    // copying values 
    vector<int> v2 =  4, 5, 6 ; 

    // Using std::back_inserter inside std::copy 
    //std::copy(v1.begin(), v1.end(), std::back_inserter(v2));  // works
    std::copy(v1.begin(), v1.end(), v2.end());  // also works
    // v2 now contains 4 5 6 1 2 3 

    // Displaying v1 and v2 
    cout << "v1 = "; 

    int i; 
    for (i = 0; i < 3; ++i)  
        cout << v1[i] << " "; 
     

    cout << "\nv2 = "; 
    for (i = 0; i < 6; ++i)  
        cout << v2[i] << " "; 
     

    return 0; 

【问题讨论】:

您的意思是std::copy(v1.begin(), v1.end(), v2.begin());?使用 v2.end() 是未定义的行为。如果capacity 足够大,它可能会起作用,因为您从不查看大小。即使这样,v2 的显示循环也无法正常工作。 @FrançoisAndrieux 不,他们都给出相同的 v2 = 4 5 6 1 2 3 @FrançoisAndrieux 我的意思是 end()。 那么你有未定义的行为,只有 看起来 像它一样有效。如果您尝试添加更多元素,它最终会失败。并尝试复制v2 并查看它是否实际上 包含这些元素。 你也可以用std::list 试试这个,它几乎肯定不会看起来像它工作。它应该会更快地崩溃。 【参考方案1】:

第一个向向量中插入值,另一个是未定义的行为,它将项目写入向量末尾的位置。

尝试打印结果向量:

std::copy(v1.begin(), v1.end(), std::back_inserter(v2));  // works
for (auto x : v2) cout << " " << x;
cout << endl;

打印

 4 5 6 1 2 3

std::copy(v1.begin(), v1.end(), v2.end());
for (auto x : v2) cout << " " << x;
cout << endl;

打印

 4 5 6

(在调试模式下会引发断言失败)

它在你的特定编译器中为你工作的事实并不能使它正确。露面工作是UB的典型表现。

【讨论】:

最有可能的是,导致 OP 混乱的一个问题不是打印内容,基于 std::vector 的大小,而是基于硬编码索引,有效地读取超过std::vector,除了写在那里。 好的,所以当我认为工作时,这一切都只是错觉。当我打印你的方式时。我只看到 4 5 6。 @user463035818 已删除:p @rustyx 当您说“它将项目插入到向量末尾的位置”时,您的意思是当我们执行std::copy(v1.begin(), v1.end(), v2.end()); 时会发生这种情况,对吗? 可以,因为end()不会修改大小,也无法保证足够的容量。

以上是关于为啥在 std::copy 期间使用 std::back_inserter 而不是 end()?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我需要另一个迭代器作为 std::copy() 中的参数?

在结构数组上使用 c++ std::copy

在啥情况下你应该更喜欢使用 std::copy 写入 cout?

使用 std::copy 时出错

使用 `std::copy()` 和 `std::back_inserter()`

是否实现了 std::copy 以使用多个线程?