传递或返回变量时并不总是调用复制构造函数

Copy constructor is not always called when passing or returning variables

本文关键字:调用 复制 构造函数 返回 变量      更新时间:2023-10-16

在这个答案中,有人提到,当按值将变量传递到函数中或作为函数的返回值传递时,不一定调用复制构造函数。有人可以解释一下这种情况何时发生以及为什么发生吗?在这种情况下,编译器如何设法返回结果?

如前所述,这就是返回值优化和复制省略。

对象是新创建然后复制时,可能会发生这种情况。在这种情况下,允许编译器对其进行优化,以便直接在正确的位置创建新对象,并且不需要复制(并且也不会调用复制构造函数)。

例如:

struct A {};
void test(A a) {}
int main() {
   test(A()); // probably there will be no copy here
}

对于返回,它是类似的。你创建一个新对象,然后如果你返回它,这将涉及一个副本,但允许编译器优化该副本(因此也包括对复制构造函数的调用)。

例如:

A returnANewA() {
    return A(); // copying would take place here
}
int main() {
    A a = returnANewA(); // the compiler is allowed to do that without copying
}

编译器如何执行此操作:根据调用约定,它知道返回值必须存储在堆栈上的位置。在其他情况下,如果编译器知道函数代码,它当然会帮助编译器。但这一切都取决于架构(x86 或其他)和编译器(GCC、Microsoft 或其他)。该标准只是说允许编译器省略对复制构造函数的调用。


如果您对有关调用约定的一些依赖于平台的详细信息感兴趣,下面是一些链接。但请注意,这些细节并不重要。您所要知道的是,编译器被允许优化复制构造函数调用(并且在大多数情况下会这样做)。

  • 维基百科x86调用约定
  • Apple 开发人员文档:IA-32 函数调用约定
  • 关于 SO 的问题:函数返回struct的调用约定