[英]Returning an fstream
我有这个功能:
fstream open_user_file() const
{
...
}
但我的编译器抱怨fstream
复制构造函数被隐式删除。 鉴于编译器执行RVO,为什么选择复制构造函数而不是移动构造函数?
否则,最好的方法是什么?
目前接受的答案是错误的。
返回具有自动存储的局部变量时,与声明的函数返回类型的类型相同,然后进行两阶段过程:
fstream open_user_file() const
{
fstream f;
/*...*/
return f;
}
首先执行对副本的构造函数的选择,就好像该对象由rvalue指定一样。
如果第一个重载决策失败或未执行,或者所选构造函数的第一个参数的类型不是对象类型的rvalue引用(可能是cv-qualified),则再次执行重载决策,将对象视为左值。
这意味着如果f
是可构造的,那么返回f
将是优选的(并且可能被省略)。 否则,如果f
是可复制的,可以完成(并且可能省略)返回f
。 否则,无法从此函数返回f
并且应该导致编译时错误。
唯一的情况是:
return std::move(f);
应该有帮助的是实施有缺陷的时候。 在符合要求的实现中, fstream
可移动构造并且:
return f;
将是最佳的。 如果f
不可移动构造,那么:
return std::move(f);
无助于符合要求的实施。 如果在符合要求的实现中编码,则会产生悲观效应,因为它会抑制RVO。
gcc 4.8没有实现可移动流(并且流不可复制)。 这是你问题的根源。 在C ++ 98,C ++ 03和gcc 4.8中,流不能从函数中返回。 在C ++ 11中,它们是。
实现可以省略由return语句产生的复制操作,即使复制构造函数具有副作用。 在这种情况下,您可能只需要明确移动。
fstream open_user_file() const
{
fstream f;
/*...*/
return std::move(f);
}
当满足某些条件时,允许实现省略类对象的复制/移动构造,即使为复制/移动操作选择的构造函数和/或对象的析构函数具有副作用。
...
这就是它说复制构造函数必须可访问的地方:
当满足或将满足复制操作的省略标准时 ,除了源对象是函数参数这一事实,并且要复制的对象由左值指定, 重载决策选择复制的构造函数是首先执行 ,好像对象是由右值指定的。 如果重载决策失败,或者所选构造函数的第一个参数的类型不是对象类型的rvalue引用(可能是cv-qualified),则再次执行重载决策,将对象视为左值。 [注意: 无论是否发生复制省略,都必须执行此两阶段重载决策。 如果未执行elision,它将确定要调用的构造函数,并且即使调用被省略,也必须可以访问所选的构造函数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.