通过值或引用传递容器

Posted

技术标签:

【中文标题】通过值或引用传递容器【英文标题】:Passing containers by value or by reference 【发布时间】:2016-05-04 02:35:42 【问题描述】:

我知道在一般情况下按值传递、引用或指针传递之间的区别。但是,我的问题是关于结构简单的容器的特殊情况。

假设这种情况:

class image
    image()=default;
    image(image const&)=default;
    ~image()=default;

    int w;
    int h;
    uchar* data;

当传递此类的对象时,复制的只是两个整数和指针,而不是整个数据。在这种情况下,是否有目的通过引用传递它?还是有目的不通过引用传递它?

引发这个问题的原因是我读到 C++ 中的 iterators 被设计为轻量级并按值传递。所以,我认为这个概念可以应用于将容器表示为实际数据而不是数据的类。

【问题讨论】:

uchar* data 是什么?我的意思是它是深度复制和清理的资源吗? 复制(非克隆)时,只复制指针,两个对象共享相同的实际数据 相关:***.com/questions/4172722/what-is-the-rule-of-three 默认析构函数不会删除data,因此显然指针指向某个外部(指向类)资源。复制这样的指针是可以的。也许wh 指的是指向数据的某个特定部分,类似于string_view 如果该类只是对其他地方管理的内存的视图,您可能应该将其称为“imageView”,以表明它仅表示图像数据的视图,而不是表示图像数据本身。 【参考方案1】:

使用默认的拷贝构造函数,任何拷贝都是浅拷贝,并且不会复制data 指向的内存。所以当你通过引用传递时,只会传递两个整数和指针,总共大约12 bytes(取决于你的架构,指针大小)。

这种差异是如此之小,以至于您通过值还是通过引用传递它并不重要。后者可能稍微快一些,因为指针可能总是可以通过 CPU 寄存器传入,而 12 字节可能不能,但这确实是微优化。 p>

我个人默认通过 (const) 引用传递除原始类型以外的任何内容,除非我有理由不这样做(请参阅 jupp0r's answer)。开发过程中的主要优势是,随着类的增长,我不必担心它什么时候变得太大并且改变我的所有函数以通过引用传递。

就默认的 C++ 迭代器而言:请注意,它们意味着基本上只是指针。事实上,我知道,对于在启用了优化的发布模式下编译的 Microsoft Visual C++,诸如std::vector 之类的连续数据结构的迭代器将减少到这一点。我不知道其他编译器是否也这样做,我会这么认为。但是,您会注意到,如果您禁用优化,那么在循环增量中写入 it++++it 之间会突然出现差异 - 纯粹是因为前一种情况下的额外复制操作。因此,如果您经常这样做,即使“复制成本低”也可能会产生影响。像往常一样:当担心性能时,根据数字进行衡量和决定。

【讨论】:

除连续数据结构外的任何迭代器都不能仅简化为指针,因为它们具有不同的语义。【参考方案2】:

恕我直言,关于如何传递参数的最佳指南可以在 Herb Sutters 的精彩演讲 Back to the Basics! Essentials of Modern C++ Style 中找到。在您的特定情况下,按值传递将是最佳选择,因为您的结构复制起来很便宜。

.

【讨论】:

你甚至可以争辩说这个结构也“移动起来很便宜”——特别是如果它有一个像 unique_ptr 这样保证支持正确移动的托管指针,并建议通过引用传递它.我认为这个特殊的例子是如此之小以至于两个论点/决定都同样有效。 重要的不仅仅是复制成本;不同的对象获得更多优化机会,因为允许编译器假设没有其他东西可以指向/引用该对象。例如:`int gi; int val(int i) gi += i; gi += 我;返回我; int ref(const int& i) gi += i; gi += 我;返回我; int main() gi = 2; std::cout

以上是关于通过值或引用传递容器的主要内容,如果未能解决你的问题,请参考以下文章

函数/变量范围(通过值或引用传递?)

C++ 是不是通过值或引用传递对象?

构造函数的最佳形式?通过值或引用传递?

如何通过值或常量引用传递 std::string_view

C# 传递参数(值或引用)?

按引用传递或按值传递指针容器之间的区别