返回一个fstream

Returning an fstream

本文关键字:一个 fstream 返回      更新时间:2023-10-16

我有这个函数:

fstream open_user_file() const
{
    ...
}

但是我的编译器抱怨fstream复制构造函数被隐式删除。既然编译器执行RVO,为什么选择复制构造函数而不是移动构造函数?

否则,最好的方法是什么?

当前接受的答案是错误的。

当返回具有自动存储的局部变量时,其类型与函数声明的返回类型相同,则有两个阶段的过程:

fstream open_user_file() const
{
    fstream f;
    /*...*/
    return f;
}
  1. 首先执行副本构造函数的选择,就好像对象是由右值指定的一样。

  2. 如果第一个重载解析失败或没有执行,或者如果所选构造函数的第一个参数的类型不是对对象类型的右值引用(可能是cv限定的),则会再次执行重载解析,将对象视为左值。

这意味着,如果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中,它们是。

即使复制构造函数有副作用,实现也可能省略由返回语句产生的复制操作。在这种情况下,您可能只需要明确移动即可。

fstream open_user_file() const
{
    fstream f;
    /*...*/
    return std::move(f);
}

当满足某些条件时,允许实现省略类的复制/移动构造对象,即使为复制/移动操作选择的构造函数和/或对象的析构函数有副作用。

这就是它所说的复制构造函数必须可访问的地方:

当满足省略复制操作的标准时或者除了源对象是一个函数参数,要复制的对象由左值指定,重载解析为选择复制首先执行的构造函数,就好像对象是由右值指定的一样。如果过载解析失败,或者如果所选构造函数的第一个参数的类型不是对的右值引用对象的类型(可能是cv限定的),再次执行重载解析,将对象视为左值。[注意:无论复制省略是否会发生它确定在不执行省略时要调用的构造函数,以及所选的构造函数必须是可访问的,即使取消了调用