当我们返回一个像vector,list这样的c ++容器时。怎么了?

时间:2017-05-23 07:05:04

标签: c++ containers return-value pass-by-reference pass-by-value

vector<int> function(...)
{
      .......
      .......
      vector<int> C = some value;
      return C
}
int main()
{
      X = function(...)
}

x的值是什么,它是C的地址,就像我们返回一个数组一样,或者返回的值是复制到X中的完整向量C.在什么情况下你应该动态分配一个容器?如果通过引用或值传递向量,最终X中是否会有任何差异?

2 个答案:

答案 0 :(得分:4)

通常,无论何时从函数返回内容,都会复制它。当这个某些东西有一个拷贝构造函数时,它就会被触发。例如数组:它们只是指向某些内存块的指针(具有普通的复制构造函数)。所以实际复制的只是指针本身。但是向量是相当复杂的类。他们有复制构造函数,实际上复制整个内容。这不能很好地扩展。

但事情就是这样:你几乎从不动态分配矢量。在许多情况下(例如在您的伪代码中),由于(已命名)返回值优化或其他copy elision optimization,内容未被复制。它实际上是相同的向量。

如果在某些情况下复制elision没有触发(或者你不确定),最好通过ref将该向量传递给函数,而不是在堆上动态分配它。在函数中分配内存然后将其返回给调用者是一种反模式(尽管有时是必要的)。这导致了一个大问题:谁负责释放内存?您需要知道函数的源代码(或至少知道文档)才能知道。

另一个选项(当复制省略不适用时)是使用std::move来避免复制。

另一方面,按值传递矢量将创建该矢量的副本。肯定你想通过ref或const ref传递它。

此外,我鼓励您自己检查所有这些事情。尝试打印原始指针&C&X以查看它是否是同一个对象。

答案 1 :(得分:0)

纯粹的语义立场,尽管它的类型名称,C是一个普通的局部变量(很可能包含三个指针:包含数据的动态缓冲区的开始,结束和容量)。

该变量在给予return语句的临时对象中移动,而该语句又被移入X变量以替换其内容。

RVO优化可以跳过第一步,通过使C变量本身存在于外部函数的堆栈框架内(主要 - 在您的情况下)。

由于您没有为X声明任何类型,我必须假设它已经存在std::vector<int>,因此=实际上是一个赋值。

由于std::vector实现了移动语义:

  1. 交换XC中的实际内部指针(以便X保留C个内容,C保留旧的X含量
  2. C被销毁
    1. C析构函数将销毁保留的旧X内容&#34;
  3. 标准库容器本身就是动态内容管理器。动态分配它们并传递它们,因为指针是C ++程序员可以做的最大的无意义。至少从2011年开始。

    如果&#34;功能&#34;不以任何方式访问X,进一步优化甚至可以通过使C为X的别名来删除赋值,以便在构造时将X的内容替换为C的内容。简单地删除了返回和=。