什么是复制省略和返回值优化? [英] What are copy elision and return value optimization?

查看:42
本文介绍了什么是复制省略和返回值优化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

什么是复制省略?什么是(命名的)返回值优化?它们意味着什么?

它们会在什么情况下发生?什么是限制?

解决方案

简介

有关技术概述 - 跳至此答案.

对于发生复制省略的常见情况 - 跳至此答案.

复制省略是大多数编译器实现的优化,用于在某些情况下防止额外的(可能代价高昂的)复制.它使按值返回或按值传递在实践中变得可行(有限制).

这是唯一一种省略(ha!)as-if 规则的优化形式 - 即使复制/移动对象有副作用,也可以应用复制省略.

以下示例取自 维基百科:

struct C {C() {}C(const C&) { std::cout <<复制了一份.
";}};C f() {返回 C();}int main() {std::cout <<你好世界!
";C obj = f();}

取决于编译器 &设置,以下输出全部有效:

<块引用>

世界你好!
复印了一份.
复印了一份.


<块引用>

世界你好!
复制了一份.


<块引用>

世界你好!

这也意味着可以创建更少的对象,因此您也不能依赖特定数量的析构函数被调用.您不应该在复制/移动构造函数或析构函数中包含关键逻辑,因为您不能依赖它们被调用.

如果省略了对复制或移动构造函数的调用,则该构造函数必须仍然存在并且必须是可访问的.这确保复制省略不允许复制通常不可复制的对象,例如因为它们有一个私有的或已删除的复制/移动构造函数.

C++17:从 C++17 开始,直接返回对象时保证复制省略:

struct C {C() {}C(const C&) { std::cout <<复制了一份.
";}};C f() {返回 C();//绝对执行复制省略}Cg(){Cc;返回 c;//也许执行复制省略}int main() {std::cout <<你好世界!
";C obj = f();//复制构造函数没有被调用}

What is copy elision? What is (named) return value optimization? What do they imply?

In what situations can they occur? What are limitations?

解决方案

Introduction

For a technical overview - skip to this answer.

For common cases where copy elision occurs - skip to this answer.

Copy elision is an optimization implemented by most compilers to prevent extra (potentially expensive) copies in certain situations. It makes returning by value or pass-by-value feasible in practice (restrictions apply).

It's the only form of optimization that elides (ha!) the as-if rule - copy elision can be applied even if copying/moving the object has side-effects.

The following example taken from Wikipedia:

struct C {
  C() {}
  C(const C&) { std::cout << "A copy was made.
"; }
};
 
C f() {
  return C();
}
 
int main() {
  std::cout << "Hello World!
";
  C obj = f();
}

Depending on the compiler & settings, the following outputs are all valid:

Hello World!
A copy was made.
A copy was made.


Hello World!
A copy was made.


Hello World!

This also means fewer objects can be created, so you also can't rely on a specific number of destructors being called. You shouldn't have critical logic inside copy/move-constructors or destructors, as you can't rely on them being called.

If a call to a copy or move constructor is elided, that constructor must still exist and must be accessible. This ensures that copy elision does not allow copying objects which are not normally copyable, e.g. because they have a private or deleted copy/move constructor.

C++17: As of C++17, Copy Elision is guaranteed when an object is returned directly:

struct C {
  C() {}
  C(const C&) { std::cout << "A copy was made.
"; }
};
 
C f() {
  return C(); //Definitely performs copy elision
}
C g() {
    C c;
    return c; //Maybe performs copy elision
}
 
int main() {
  std::cout << "Hello World!
";
  C obj = f(); //Copy constructor isn't called
}

这篇关于什么是复制省略和返回值优化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆