在C ++中复制向量的不同方法

在本文中,我们将看到如何以各种方式将一个向量复制到另一个向量中?在检查每种向量复制方法时,我们还将了解浅复制和深复制,它们的区别以及后果。

在开始将向量复制到另一个向量的方法之前,让我们讨论什么是浅拷贝和深拷贝。它们之间有什么区别,为什么我们需要两个不同的术语来对复制过程进行分类。

浅拷贝与深拷贝

向量本质上是一个在执行时具有一些内存分配的对象。现在说您已经定义并声明了一些向量A,并且想要将A的内容复制到另一个向量B中。现在,可能有两种情况,一种情况是我们定义了一个新的向量B,但没有为此分配任何新的内存,只是链接到向量A,类似向量B指向向量A的相同位置。因此,它具有向量A的相同副本。这被称为浅表副本。如果即使在完成复制操作后对向量A进行任何更改,则向量B 会有相同的变化,这是不希望的。

另一方面,当我们为向量B创建新位置并复制向量A中的内容时,则称为Deep copy。如果我们在复制操作后对向量A进行了任何更改,它都不会反映在向量B中,这当然是有意的。

在讨论复制方法时,我们将详细说明它是浅复制还是深复制以及原因,这样您就永远不会使用复制方法犯任何错误,而猜测它是深复制!(是的,通常我们通常打算复制一个深层副本)。

不同的复印方式

1)反复复制内容

在这里,我们简单地将向量A的内容迭代地复制到向量B中。向量B被定义为新位置,因此它当然是深层副本。我们也通过在复制操作后更改元素来验证这一点。

示例代码:

#include <bits/stdc++.h>
using namespace std;

int main(){
    //向量A; 
    //5个元素的向量,其中每个 
    //元素是-1-
    vector<int> A(5, -1); 

    cout << "printing vector A:\n";
    for (auto it : A)
        cout << it << " ";
    cout << endl;

    //定义的向量B-
    vector<int> B;

    //反复复制内容
    for (int i = 0; i < A.size(); i++) {
        B.push_back(A[i]);
    }
    cout << "Vector A copied into vector B\n";
    cout << "printing vector B:\n";
    for (auto it : B)
        cout << it << " ";
    cout << endl;

    //检查深层副本或浅层副本
    //更改向量A中的一个元素
    A[4] = 4;

    cout << "After making the change...\n";

    //打印向量A-
    cout << "printing vector A:\n";
    for (auto it : A)
        cout << it << " ";
    cout << endl;
    
    //打印向量B-
    cout << "printing vector B:\n";
    for (auto it : B)
        cout << it << " ";
    cout << endl;

    cout << "No change in B, it's deep copy!\n";

    return 0;
}

输出:

printing vector A:
-1 -1 -1 -1 -1
Vector A copied into vector B
printing vector B:
-1 -1 -1 -1 -1
After making the change...
printing vector A:
-1 -1 -1 -1 4
printing vector B:
-1 -1 -1 -1 -1
No change in B, it's deep copy!

2)递归复制内容

在这里,我们简单地将向量A的内容递归复制到向量B中。向量B被定义为新位置,因此它当然是深层副本。我们也通过在复制操作后更改元素来验证这一点。

示例代码:

#include <bits/stdc++.h>
using namespace std;

//递归复制
//检查参考传递给向量B-
void myrecur(int i, vector<int> A, vector<int>& B)
{
    //基本情况
    if (i == A.size())
        return;

    //复制内容
    B.push_back(A[i]);
    myrecur(i + 1, A, B);
}

int main(){
    //向量A; 
    //5个元素的向量,其中每个 
    //元素是-1-
    vector<int> A(5, -1); 

    cout << "printing vector A:\n";
    for (auto it : A)
        cout << it << " ";
    cout << endl;

    //定义的向量B-
    vector<int> B;

    //反复复制内容
    myrecur(0, A, B);
    cout << "Vector A copied into vector B\n";
    cout << "printing vector B:\n";
    for (auto it : B)
        cout << it << " ";
    cout << endl;

    //检查深层副本或浅层副本
    //更改向量A中的一个元素
    A[4] = 4;

    cout << "After making the change...\n";

    //打印向量A-
    cout << "printing vector A:\n";
    for (auto it : A)
        cout << it << " ";
    cout << endl;
    //打印向量B-
    cout << "printing vector B:\n";
    for (auto it : B)
        cout << it << " ";
    cout << endl;

    cout << "No change in B, it's deep copy!\n";

    return 0;
}

输出:

printing vector A:
-1 -1 -1 -1 -1
Vector A copied into vector B
printing vector B:
-1 -1 -1 -1 -1
After making the change...
printing vector A:
-1 -1 -1 -1 4
printing vector B:
-1 -1 -1 -1 -1
No change in B, it's deep copy!

3)使用赋值运算符“ =”(覆盖当前内容)

将向量复制到另一个向量的另一种方法是使用赋值运算符。是的,它运作完美!根本不要尝试使用静态数组!之所以使用这种赋值运算符,是因为它会简单地覆盖当前成员(如果有)的原因,否则会从其复制位置赋值。下面是一个示例,我们可以看到,它是一个深层副本。

注意:在Java中,赋值运算符仅执行浅表副本。

示例代码:

#include <bits/stdc++.h>
using namespace std;

int main(){
    //向量A; 
    //5个元素的向量,其中每个 
    //元素是-1-
    vector<int> A(5, -1); 

    cout << "printing vector A:\n";
    for (auto it : A)
        cout << it << " ";
    cout << endl;

    //定义的向量B- and copy A 
    //与赋值运算符
    vector<int> B = A;

    cout << "Vector A copied into vector B\n";
    cout << "printing vector B:\n";
    for (auto it : B)
        cout << it << " ";
    cout << endl;

    //检查深层副本或浅层副本
    //更改向量A中的一个元素
    A[4] = 4;

    cout << "After making the change...\n";

    //打印向量A-
    cout << "printing vector A:\n";
    for (auto it : A)
        cout << it << " ";
    cout << endl;
    
    //打印向量B-
    cout << "printing vector B:\n";
    for (auto it : B)
        cout << it << " ";
    cout << endl;

    cout << "No change in B, it's deep copy!\n";

    return 0;
}

输出:

printing vector A:
-1 -1 -1 -1 -1
Vector A copied into vector B
printing vector B:
-1 -1 -1 -1 -1
After making the change...
printing vector A:
-1 -1 -1 -1 4
printing vector B:
-1 -1 -1 -1 -1
No change in B, it's deep copy!

4)使用复制构造函数

我们还可以将向量A作为构造函数传递给向量B,后者将调用复制构造函数并提供深层复制

示例代码:

#include <bits/stdc++.h>
using namespace std;

int main(){
    //向量A; 
    //5个元素的向量,其中每个 
    //元素是-1-
    vector<int> A(5, -1); 

    cout << "printing vector A:\n";
    for (auto it : A)
        cout << it << " ";
    cout << endl;

    //定义的向量B- and vector  
    //传入构造函数
    //这也被认为是 
    //初始化方法
    vector<int> B(A);

    cout << "Vector A copied into vector B\n";
    cout << "printing vector B:\n";
    for (auto it : B)
        cout << it << " ";
    cout << endl;

    //检查深层副本或浅层副本
    //更改向量A中的一个元素

    A[4] = 4;

    cout << "After making the change...\n";

    //打印向量A-
    cout << "printing vector A:\n";
    for (auto it : A)
        cout << it << " ";
    cout << endl;
    //打印向量B-
    cout << "printing vector B:\n";
    for (auto it : B)
        cout << it << " ";
    cout << endl;

    cout << "No change in B, it's deep copy!\n";

    return 0;
}

输出:

printing vector A:
-1 -1 -1 -1 -1
Vector A copied into vector B
printing vector B:
-1 -1 -1 -1 -1
After making the change...
printing vector A:
-1 -1 -1 -1 4
printing vector B:
-1 -1 -1 -1 -1
No change in B, it's deep copy!

5)std :: copy()函数

还有一种使用std函数copy()的方法。尽管使用较少,但您应该了解C ++标准库具有的各种功能。是的,它可以进行深层复制。
复制函数需要三个参数

第一个是:从何处开始复制的迭代器:向量A的开始

第二个是:结束复制的迭代器:向量A的结尾

第三个是:指向目标向量的输出迭代器:向量B的开头

所以语法是

void copy(argumnet1, argument2, argument3)

示例代码:

#include <bits/stdc++.h>
using namespace std;

int main(){
    //向量A; 
    //5个元素的向量,其中每个 
    //元素是-1-
    vector<int> A(5, -1); 

    cout << "printing vector A:\n";
    for (auto it : A)
        cout << it << " ";
    cout << endl;

    //定义的向量B-
    vector<int> B(5);

    //复制

    copy(A.begin(), A.end(), B.begin());

    cout << "Vector A copied into vector B\n";
    cout << "printing vector B:\n";
    for (auto it : B)
        cout << it << " ";
    cout << endl;

    //检查深层副本或浅层副本
    //更改向量A中的一个元素

    A[4] = 4;

    cout << "After making the change...\n";

    //打印向量A-
    cout << "printing vector A:\n";
    for (auto it : A)
        cout << it << " ";
    cout << endl;
    //打印向量B-
    cout << "printing vector B:\n";
    for (auto it : B)
        cout << it << " ";
    cout << endl;

    cout << "No change in B, it's deep copy!\n";

    return 0;
}

输出:

printing vector A:
-1 -1 -1 -1 -1
Vector A copied into vector B
printing vector B:
-1 -1 -1 -1 -1
After making the change...
printing vector A:
-1 -1 -1 -1 4
printing vector B:
-1 -1 -1 -1 -1
No change in B, it's deep copy!

关于上述代码的非常重要的注意事项:

检查这里我已经将向量B定义为vector <int> B(5),但是如果您查看以前的代码,您会发现我已经将向量B定义为vector <int> B

现在的问题是,为什么这次我要进行更改。有什么原因还是我只是这样做了!好的,我们可以像以前一样做。

然后代码将是:

#include <bits/stdc++.h>
using namespace std;

int main(){
    //向量A; 
    //5个元素的向量,其中每个 
    //元素是-1-
    vector<int> A(5, -1); 

    cout << "printing vector A:\n";
    for (auto it : A)
        cout << it << " ";
    cout << endl;

    //定义的向量B-
    vector<int> B;

    //复制

    copy(A.begin(), A.end(), B.begin());

    cout << "Vector A copied into vector B\n";
    cout << "printing vector B:\n";
    for (auto it : B)
        cout << it << " ";
    cout << endl;

    //检查深层副本或浅层副本
    //更改向量A中的一个元素
    A[4] = 4;

    cout << "After making the change...\n";

    //打印向量A-
    cout << "printing vector A:\n";
    for (auto it : A)
        cout << it << " ";
    cout << endl;
    //打印向量B-
    cout << "printing vector B:\n";
    for (auto it : B)
        cout << it << " ";
    cout << endl;

    cout << "No change in B, it's deep copy!\n";

    return 0;
}

输出:

printing vector A:
-1 -1 -1 -1 -1
Segmentation fault (core dumped)

糟糕!输出是分段错误!。为什么?也许现在您明白了。每当我们写vector <int> B时,向量都不知道会有多少个元素,也根本不为元素分配内存。但是在我们的复制函数中,有一个输出迭代器试图遍历向量B,但是由于没有为元素分配内存而失败。这就是分割错误的原因,我们需要分配内存,而不是说定义向量及其元素。这就是为什么我们需要vector <int> B(5)的原因。浏览我有关矢量初始化方法的文章,以了解有关此内容的详细信息。糟糕,一个小错误可能会导致您出现细分错误,并且您可能会疯狂地找到该错误!我希望这堂课很好。

6)vector :: assign()函数

Vector也具有内置功能,可以从其他内容复制内容。它被命名为assign()函数。这又是一种深层复制方法。

语法如下所示,

destination_vector.assign (
    iterator to the beginning of source_vector, 
    an iterator to the end of source_vector
    );

示例代码:

#include <bits/stdc++.h>
using namespace std;

int main(){
    //向量A; 
    //5个元素的向量,其中每个 
    //元素是-1-
    vector<int> A(5, -1); 

    cout << "printing vector A:\n";
    for (auto it : A)
        cout << it << " ";
    cout << endl;

    //定义的向量B-
    vector<int> B;

    //使用vector :: assign复制
    B.assign(A.begin(), A.end());

    cout << "Vector A copied into vector B\n";
    cout << "printing vector B:\n";
    for (auto it : B)
        cout << it << " ";
    cout << endl;

    //检查深层副本或浅层副本
    //更改向量A中的一个元素
    A[4] = 4;

    cout << "After making the change...\n";

    //打印向量A-
    cout << "printing vector A:\n";
    for (auto it : A)
        cout << it << " ";
    cout << endl;
    
    //打印向量B-
    cout << "printing vector B:\n";
    for (auto it : B)
        cout << it << " ";
    cout << endl;

    cout << "No change in B, it's deep copy!\n";

    return 0;
}

输出:

printing vector A:
-1 -1 -1 -1 -1
Vector A copied into vector B
printing vector B:
-1 -1 -1 -1 -1
After making the change...
printing vector A:
-1 -1 -1 -1 4
printing vector B:
-1 -1 -1 -1 -1
No change in B, it's deep copy!

好的,仅此而已。因此,我们发现所有复制方法实际上都做得很好,因为它们都进行深度复制,因此我们可以盲目使用其中任何一种。请发表评论,让我们知道您喜欢哪种复制方法,为什么?