Meh*_*dad 22 c++ copy-constructor implicit-conversion copy-elision
以下代码在Visual C++ 2013中编译良好,但不在GCC或Clang下编译.
哪个是对的?
通过隐式转换返回对象时是否需要可访问的复制构造函数?
class Noncopyable
{
Noncopyable(Noncopyable const &);
public:
Noncopyable(int = 0) { }
};
Noncopyable foo() { return 0; }
int main()
{
foo();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
GCC:
error: 'Noncopyable::Noncopyable(const Noncopyable&)' is private
Noncopyable(Noncopyable const &);
^
error: within this context
Noncopyable foo() { return 0; }
Run Code Online (Sandbox Code Playgroud)
铛:
error: calling a private constructor of class 'Noncopyable'
Noncopyable foo() { return 0; }
^
note: implicitly declared private here
Noncopyable(Noncopyable const &);
^
warning: C++98 requires an accessible copy constructor for class 'Noncopyable' when binding a reference to a temporary; was private [-Wbind-to-temporary-copy]
Noncopyable foo() { return 0; }
^
note: implicitly declared private here
Noncopyable(Noncopyable const &);
^
Run Code Online (Sandbox Code Playgroud)
Rei*_*ica 15
当您return使用表达式时,将创建一个返回类型的临时对象,使用该表达式初始化,然后将其移动(或复制,如果移动不是一个选项),则返回到返回值.所以你需要一个可访问的副本或移动构造函数.
但是,可以使用支撑列表直接初始化返回值.以下是有效的:
Noncopyable foo() { return {0}; }
Run Code Online (Sandbox Code Playgroud)
类似的情况在活生生的例子.
12.8复制和移动类对象[class.copy]
1/类对象可以通过两种方式复制或移动:初始化(12.1,8.5),包括函数参数传递(5.2.2)和函数值返回(6.6.3); [...]
在6.6.3返回语句[stmt.return]:
2/[...]表达式的值隐式转换为它出现的函数的返回类型.返回声明可能涉及构造和复制或移动临时对象(12.2)[...]
和12.2临时对象[class.temporary]:
1/类型的临时数在各种上下文中创建:绑定对prvalue的引用(8.5.3),返回prvalue(6.6.3),创建prvalue的转换(4.1,5.2.9,5.2.11, 5.4),[...]注意:即使没有调用析构函数或复制/移动构造函数,所有语义限制,如可访问性(第11条)和函数是否被删除(8.4.3),都应满意.[...]
我认为GCC和clang是正确的 - 我甚至会说,无论何时按值返回,返回类型都必须有一个可访问的副本或移动构造函数.
逻辑是创建临时文件以将原始类型转换为新类型(intto Noncopyable),然后为该函数返回该临时文件的副本.
它的基本相同:
Noncopyable foo() { return Noncopyable(0); }
Run Code Online (Sandbox Code Playgroud)
你希望那里需要一份副本吗?我当然会.
| 归档时间: |
|
| 查看次数: |
1741 次 |
| 最近记录: |