vector<int> function(...)
{
.......
.......
vector<int> C = some value;
return C
}
int main()
{
X = function(...)
}
x的值是什么,它是C的地址,就像我们返回一个数组一样,或者返回的值是复制到X中的完整向量C.在什么情况下你应该动态分配一个容器?如果通过引用或值传递向量,最终X中是否会有任何差异?
答案 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
实现了移动语义:
X
和C
中的实际内部指针(以便X
保留C
个内容,C
保留旧的X
含量C
被销毁
C
析构函数将销毁保留的旧X
内容&#34; 标准库容器本身就是动态内容管理器。动态分配它们并传递它们,因为指针是C ++程序员可以做的最大的无意义。至少从2011年开始。
如果&#34;功能&#34;不以任何方式访问X,进一步优化甚至可以通过使C为X的别名来删除赋值,以便在构造时将X的内容替换为C的内容。简单地删除了返回和=。