下面的代码在Visual C++ 2013中编译得很好,但不是在GCC或Clang下编译的。
哪个是对的?
通过隐式转换返回对象时是否需要可访问的复制构造函数?
class Noncopyable
{
Noncopyable(Noncopyable const &);
public:
Noncopyable(int = 0) { }
};
Noncopyable foo() { return 0; }
int main()
{
foo();
return 0;
}GCC:
error: 'Noncopyable::Noncopyable(const Noncopyable&)' is private
Noncopyable(Noncopyable const &);
^
error: within this context
Noncopyable foo() { return 0; }嘎吱声:
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 &);
^发布于 2014-06-16 08:10:57
当您创建一个表达式时,会创建一个返回类型的临时对象,并使用该表达式初始化该对象,然后将该对象(如果不是return选项)移到返回值中。因此,您需要一个可访问的副本或移动构造函数。
但是,可以使用带括号的列表直接初始化返回值。因此,以下工作:
Noncopyable foo() { return {0}; }实例化中也有类似的情况。
发布于 2014-06-16 08:00:46
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是正确的--我甚至会说,只要您按值返回,返回类型就必须有一个可访问的副本或移动构造函数。
逻辑是创建一个临时类型以将原始类型转换为新类型(int到Noncopyable),然后创建该临时类型的副本以返回函数。
它本质上与以下内容相同:
Noncopyable foo() { return Noncopyable(0); }你希望那里需要一份副本吗?我当然会的。
发布于 2014-06-16 08:11:08
foo按值返回Noncopyable对象。因此,从理论上讲,必须调用副本构造函数。public)并打印一条消息来标记它的唤起,您将看到该消息没有打印演示,并且只会引发重载的转换操作符。foo的返回语句需要一个副本构造函数,因为您按值返回。https://stackoverflow.com/questions/24238786
复制相似问题