为什么按值传递时复制c ++向量内部元素/数组

phanhuy152

当向量按值传递时,为什么复制向量的内部元素?

#include<vector>
using namespace std;

// this func won't modify v[2]. 
// Meaning v[2] (and the whole inner array) was copied 
// when v is passed to the func?
void modify(vector<int> v) {
    v[2] = 100;
}

// this func modify v[2]
void modify(vector<int>& v) {
    v[2] = 100;
}

int main() {
    vector<int> v = {1,2,3,4,5,6};

    // still same
    modify(v);

    // modified
    modified2(v);
}

我发现奇怪的是,当按值传递向量时,会复制向量的实际内容。我认为std :: vector实现必须具有一个指针字段,该字段映射到实际数组所在的堆上的地址。因此,即使通过值传递向量,地址也应保持不变,指向相同的内容。像这样:

#include<iostream>

using namespace std;

// a dummy wrapper of an array
// trying to mock vector<int>
class vector_int {
    public:
    int* inner_array; // the actual array 
    vector_int(int *a) {
        inner_array = a;
    }
    int* at(int pos) {
        return inner_array+pos;
    }
};

// this passes the "mocked vector" by value
// but 'inner_array' is not copied
void modify(vector_int v) {
    *(v.at(2)) = 10;
}

int main() {
    int* a = new int[3] {1,2,3};
    vector_int v = vector_int(a);
    modify(v); // v[2] is modified
}

这个关于std :: vector实现的假设正确吗?通过值传递复制矢量内容的原因是什么?


编辑

多亏了igel的回答和UnholySheep的评论,我才弄清了std :: vector具有价值的重要性(或内部数组被复制的原因)的原因。

如果在类定义中显式定义了复制构造函数类,则复制构造函数将确定在函数调用中传递变量时如何复制struct / class实例因此,我可以为我定义一个复制构造函数vector_int,在其中复制整个内容inner_array,例如

#include<iostream>

using namespace std;

class vector_int {
    public:
    int* inner_array;
    int len;
    vector_int(int *a, int len) {
        inner_array = a;
        this->len = len;
    }
    int* at(int pos) {
        return inner_array+pos;
    }
    // this is the copy constructor
    vector_int(const vector_int &v2) {
        inner_array = new int;
        for (int i =0; i < v2.len; i++) {
            *(inner_array+i) = *(v2.inner_array+i);
        }
    } 
};

// Yay, the vector_int's inner_array is copied
// when this function is called
// and no modification of the original vector is done
void modify(vector_int v) {
    *(v.at(2)) = 10;
}

int main() {
    int* a = new int[3] {1,2,3};
    vector_int v = vector_int(a,3);
    // 
    modify(v);
}

我在本地计算机(g ++ Apple LLVM版本10.0.0)上检查了stdlib实现的源代码。std :: vector定义了一个复制构造函数,看起来像这样

template <class _Tp, class _Allocator>
vector<_Tp, _Allocator>::vector(const vector& __x)
    : __base(__alloc_traits::select_on_container_copy_construction(__x.__alloc()))
{
    size_type __n = __x.size();
    if (__n > 0)
    {
        allocate(__n);
        __construct_at_end(__x.__begin_, __x.__end_, __n);
    }
}

它看起来像为实际复制的数组做malloc +复制该数组。

老刺猬

C ++允许类类型为其创建,复制,移动和销毁的含义提供自己的代码,并且隐式调用该代码,而无需进行任何明显的函数调用。这就是所谓的语义值,它就是C ++使用,而其他语言诉诸一些事情,如create_foo(foo)foo.clone()destroy_foo(foo)foo.dispose()

每个类都可以定义以下特殊成员函数

  • 构造函数,用于将对象置于有效的初始状态
  • 销毁者,负责任地清理
  • 复制构造函数,用于创建与另一个对象重复的新对象
  • 移动构造函数,用于通过传输另一个对象的数据来创建新对象
  • 复制分配运算符,用于将对象复制到现有对象中
  • 移动分配运算符,用于在两个现有对象之间传输数据

您可以定义所有这些功能以执行所需的任何操作。但是它们被隐式调用,这意味着此类的用户在他们的代码中看不到这些函数调用,他们希望它们做可预测的事情。您应遵循“三/五/零规则,确保您的班级表现可预测

当然,您已经知道其他用于共享数据的工具,例如传递引用。

标准库中的许多类都使用这些特殊的成员函数来实现特殊的行为,这些行为非常有用并有助于用户编写安全正确的代码。例如:

  • std::vector 复制时,尽管底层数组和包含的对象将是单独的,但它们将始终具有相同的元素。
  • std::unique_ptr包装拥有一个所有者的资源要强制执行此操作,无法将其复制
  • std::shared_ptr包装具有许多所有者的资源何时清除此类资源尚不完全清楚,因此复制shared_ptr会执行自动引用计数,并且仅在最后一个所有者完成后才清除该资源。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

零元素数组的需求是什么?

来自分类Dev

计算字符串数组c#中的元素数

来自分类Dev

按类排列的元素数组-TypeError:$ .id不是函数

来自分类Dev

从python中的多值元素数组中打印特定值

来自分类Dev

查找作为参数传递给函数的数组中的元素数。

来自分类Dev

C中多维数组的内部数组的元素数

来自分类Dev

增加元素数组中的字段的值

来自分类Dev

创建元素数组C#控制台

来自分类Dev

通过调用函数从元素数组中删除重复的值

来自分类Dev

PHP复制x for循环中的数组元素数量

来自分类Dev

C按值传递数组vs按引用传递数组

来自分类Dev

为什么按值传递的数组上的std :: size不起作用?

来自分类Dev

在C语言中,为什么将sizeof函数用作存储数组中元素数量的分母?

来自分类Dev

PySpark-获取具有相同值的数组的元素数

来自分类Dev

当元素数> 1000时,如何使向量的笛卡尔积?

来自分类Dev

获取它在数组中具有值的元素数

来自分类Dev

在MongoDB中搜索子元素数组值

来自分类Dev

为什么数组有时通过值传递而不是其他时候传递?

来自分类Dev

C语言中的sprintf(指向char元素数组的指针)

来自分类Dev

获取结构数组C ++中的元素数

来自分类Dev

当计数显示内部元素数时,数组中出现未定义的偏移量错误

来自分类Dev

C:为什么您可以按值传递结构(而不是数组)(给函数)?

来自分类Dev

将C编程元素数组放入sprintf()

来自分类Dev

从字符串中获取元素数组并查找值

来自分类Dev

从对象字段按顺序访问对象元素数组?

来自分类Dev

Python 中的单元素数组数组:为什么?

来自分类Dev

将单元素数组传递给 SendInput 是错误吗?

来自分类Dev

C# 查找数组中存在的元素数

来自分类Dev

合并 2 个数组保留内部元素数组值

Related 相关文章

  1. 1

    零元素数组的需求是什么?

  2. 2

    计算字符串数组c#中的元素数

  3. 3

    按类排列的元素数组-TypeError:$ .id不是函数

  4. 4

    从python中的多值元素数组中打印特定值

  5. 5

    查找作为参数传递给函数的数组中的元素数。

  6. 6

    C中多维数组的内部数组的元素数

  7. 7

    增加元素数组中的字段的值

  8. 8

    创建元素数组C#控制台

  9. 9

    通过调用函数从元素数组中删除重复的值

  10. 10

    PHP复制x for循环中的数组元素数量

  11. 11

    C按值传递数组vs按引用传递数组

  12. 12

    为什么按值传递的数组上的std :: size不起作用?

  13. 13

    在C语言中,为什么将sizeof函数用作存储数组中元素数量的分母?

  14. 14

    PySpark-获取具有相同值的数组的元素数

  15. 15

    当元素数> 1000时,如何使向量的笛卡尔积?

  16. 16

    获取它在数组中具有值的元素数

  17. 17

    在MongoDB中搜索子元素数组值

  18. 18

    为什么数组有时通过值传递而不是其他时候传递?

  19. 19

    C语言中的sprintf(指向char元素数组的指针)

  20. 20

    获取结构数组C ++中的元素数

  21. 21

    当计数显示内部元素数时,数组中出现未定义的偏移量错误

  22. 22

    C:为什么您可以按值传递结构(而不是数组)(给函数)?

  23. 23

    将C编程元素数组放入sprintf()

  24. 24

    从字符串中获取元素数组并查找值

  25. 25

    从对象字段按顺序访问对象元素数组?

  26. 26

    Python 中的单元素数组数组:为什么?

  27. 27

    将单元素数组传递给 SendInput 是错误吗?

  28. 28

    C# 查找数组中存在的元素数

  29. 29

    合并 2 个数组保留内部元素数组值

热门标签

归档