'explicit'关键字对返回值优化(RVO)有什么影响? [英] What is the effect of 'explicit' keyword on the Return Value Optimization (RVO)?

查看:112
本文介绍了'explicit'关键字对返回值优化(RVO)有什么影响?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面的代码可以很好地工作(显示RVO):

Following code works perfectly fine (showing RVO):

struct A { 
  A (int) { cout << "A::A()\n"; }  // constructor
  A (const A&) { cout << "A::A(const A&)\n"; }  // copy constructor
};

A foo () { return A(0); }

int main () {
  A a = foo();
}

输出:

A::A()  // --> which means copy constructor is not called

如果我将副本构造函数标记为 explicit

If I mark the copy constructor as explicit:

explicit A (const A&) { ... }

然后编译器出错:

explicit.cpp: In function ‘A foo()’:
explicit.cpp:10:22: error: no matching function for call to ‘A::A(A)’
 A foo () { return A(0); }
                      ^
explicit.cpp:5:3: note: candidate: A::A(int)
   A (int) { cout << "A::A()\n"; }
   ^
explicit.cpp:5:3: note:   no known conversion for argument 1 from ‘A’ to ‘int’
explicit.cpp: In function ‘int main()’:
explicit.cpp:14:13: error: no matching function for call to ‘A::A(A)’
   A a = foo();
             ^
explicit.cpp:5:3: note: candidate: A::A(int)
   A (int) { cout << "A::A()\n"; }
   ^
explicit.cpp:5:3: note:   no known conversion for argument 1 from ‘A’ to ‘int’

为什么会发生,RVO是否应该按原样工作?

Why is it happening, Shouldn't the RVO work as it is?

推荐答案

RVO可以取消副本,但是语言规则要求必须仍然可以进行副本(或移动):

RVO can elide a copy, but the language rules require that a copy (or a move) must still be possible:


[C ++ 14:12.8 / 31]:满足某些条件时,即使选择了用于复制/删除的构造函数,也允许实现省略类对象的复制/移动构造。移动操作和/或对象的析构函数具有副作用。 [..]

[C++14: 12.8/31]: When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object, even if the constructor selected for the copy/move operation and/or the destructor for the object have side effects. [..]

[C ++ 14:12.8 / 32]: [ ..] [注意:无论是否出现复制省略,都必须执行此两阶段重载解析。如果不执行省略操作,它将确定要调用的构造函数,并且即使取消了调用,所选的构造函数也必须可访问。 -尾注]

[C++14: 12.8/32]: [..] [ Note: This two-stage overload resolution must be performed regardless of whether copy elision will occur. It determines the constructor to be called if elision is not performed, and the selected constructor must be accessible even if the call is elided. —end note ]

您通过添加 explicit ,并且无法进行移动,因为您的副本构造函数阻止了隐式定义的移动构造函数的创建。

You made the copy impossible by adding explicit, and a move is not possible because your copy constructor blocks the creation of an implicitly-defined move constructor.

您可以允许移动,而不必添加自己的移动构造函数,也许是默认的一个:

You could allow a move instead by adding your own move constructor, perhaps a defaulted one:

A(A&&) = default;

但这只是遵守相同语言规则的另一种方式。

But this is only another way of abiding by the same language rule.

无论如何,C ++ 17都会通过添加一些不受复制约束的保证来放宽该规则。

C++17 will relax the rule somewhat anyway, by adding some guarantees of copy elision which will not be subject to this constraint.

这篇关于'explicit'关键字对返回值优化(RVO)有什么影响?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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