C++复制构造函数、临时对象和复制语义

发布于 2024-08-23 02:51:47 字数 554 浏览 5 评论 0原文

对于这个程序,

#include <iostream>
using std::cout;

struct C 
{
    C() { cout << "Default C called!\n"; }
    C(const C &rhs) { cout << "CC called!\n"; }
};

const C f()
{
    cout << "Entered f()!\n";
    return C();
}

int main()
{
    C a = f();
    C b = a;

    return 0;
}

我得到的输出是:

Entered f()!
Default C called!
CC called!

由于 f() 按值返回,因此它应该返回一个临时值。由于 T a = x;T a(x);,它不会调用复制构造函数来构造 a,临时传入作为其参数?

For this program

#include <iostream>
using std::cout;

struct C 
{
    C() { cout << "Default C called!\n"; }
    C(const C &rhs) { cout << "CC called!\n"; }
};

const C f()
{
    cout << "Entered f()!\n";
    return C();
}

int main()
{
    C a = f();
    C b = a;

    return 0;
}

the output I get is:

Entered f()!
Default C called!
CC called!

Since f() is returning by value, it should return a temporary. As T a = x; is T a(x);, wouldn't it call the copy constructor for the construction of a, with the temporary passed-in as its argument?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

誰ツ都不明白 2024-08-30 02:51:48

这是您的编译器支持的返回值优化(RVO)功能的示例。

当您按值返回时,复制构造函数可能不会被调用。

在 GCC 上使用 -fno-elide-constructors 选项来关闭该功能。

This is an example of Return Value Optimization(RVO) features which your compiler supports.

A copy constructor might not be called when you return by value.

Use -fno-elide-constructors option on GCC to turn that feature off.

灼痛 2024-08-30 02:51:48

我相信它被称为返回值优化

我假设当f() 返回 C 对象,该对象在调用方法的堆栈空间中分配,因此不需要复制来初始化 C a。这是您的默认 C 调用

C b = a

这会导致复制构造函数,因此您的 CC 被调用

顺便说一句,维基百科上的示例看起来与您的代码非常相似。

I believe it's called return value optimization.

I assume when f() returns C object the object is allocated in the stack space of the calling method therefore no copy is required to initialize C a. This is your default C called.

C b = a

This causes a copy constructor hence your CC called.

Btw, the example on wiki looks quite like similar to your code.

欢烬 2024-08-30 02:51:47

由于 f() 按值返回,因此它应该返回一个临时值。由于 T a = x;T a(x);,它不会调用复制构造函数来构造 a,临时传入作为其参数?

查找返回值优化。默认情况下此功能处于打开状态。如果您在 Windows 上使用 MSVC 2005+,则可以使用 /Od 关闭此功能并获得所需的结果(或在 GCC 上使用 -fno-elide-constructors)。另外,对于 MSVC,请参阅文章。

12.8 复制类对象

15 当满足某些条件时,
实现可以省略
类对象的复制构造,
即使复制构造函数和/或
对象的析构函数有侧面
影响。在这种情况下,
实施处理源头和
省略的复制操作的目标
只是两种不同的方式
引用同一个对象,并且
该对象的破坏发生在
两者中较晚的时候
物体会有
没有被摧毁
optimization.115 这种复制的省略
操作被允许在
以下情况(可能是
组合起来消除多个
份):

在返回语句中
具有类返回类型的函数,

当表达式是 a 的名称时
非易失性自动对象
与以下相同的 cv-unqualified 类型
函数返回类型,副本
操作可以省略
构造自动对象
直接进入函数的return
价值
— 在 throw 表达式中,当
操作数是 a 的名称
非易失性自动对象,
将操作数从操作数复制到
异常对象(15.1)可以省略
通过构造自动对象
直接进入异常对象


当一个临时类对象具有
没有被绑定到参考(12.2)
将被复制到一个类对象
相同的简历非限定类型,副本
操作可以省略
构造临时对象
直接进入目标
省略副本

——当
异常-异常声明
handler(第 15 条)声明一个对象
相同类型(除了
简历资格)作为例外
对象(15.1),复制操作可以
通过处理被省略
异常声明作为别名
异常对象 if 的含义
该程序将保持不变,除了
用于构造函数的执行和
声明的对象的析构函数
异常声明。

注意:强调我的

Since f() is returning by value, it should return a temporary. As T a = x; is T a(x);, wouldn't it call the copy constructor for the construction of a, with the temporary passed-in as its argument?

Look up Return Value Optimization. This is turned on by default. If you are on Windows using MSVC 2005+ you can use /Od to turn this off and get the desired result (or -fno-elide-constructors on GCC). Also, for MSVC see this article.

12.8 Copying class objects

15 When certain criteria are met, an
implementation is allowed to omit the
copy construction of a class object,
even if the copy constructor and/or
destructor for the object have side
effects. In such cases, the
implementation treats the source and
target of the omitted copy operation
as simply two different ways of
referring to the same object, and the
destruction of that object occurs at
the later of the times when the two
objects would have
been destroyed without the
optimization.115 This elision of copy
operations is permitted in the
following circumstances (which may be
combined to eliminate multiple
copies):

in a return statement in a
function with a class return type,

when the expression is the name of a
non-volatile automatic object with the
same cv-unqualified type as the
function return type, the copy
operation can be omitted by
constructing the automatic object
directly into the function’s return
value
— in a throw-expression, when
the operand is the name of a
non-volatile automatic object, the
copy operation from the operand to the
exception object (15.1) can be omitted
by constructing the automatic object
directly into the exception object


when a temporary class object that has
not been bound to a reference (12.2)
would be copied to a class object with
the same cv-unqualified type, the copy
operation can be omitted by
constructing the temporary object
directly into the target of the
omitted copy

— when the
exception-declaration of an exception
handler (Clause 15) declares an object
of the same type (except for
cv-qualification) as the exception
object (15.1), the copy operation can
be omitted by treating the
exception-declaration as an alias for
the exception object if the meaning of
the program will be unchanged except
for the execution of constructors and
destructors for the object declared by
the exception-declaration.

Note: Emphasis mine

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文