自动和复制省略

3
当使用auto并且确定了特定类型时,复制省略的规则是什么?(见:GotW - Almost always auto)。
据我所知,尽管通常不使用移动/复制构造函数,但需要使其可访问。但下面示例中的unique_ptr和fstream有什么区别?(与noexcept有关吗?)
#include <memory>
#include <fstream>

int main()
{
    auto f = std::fstream{"foo.bar"};
    auto i = std::unique_ptr<int>{new int};

    return 0;
}


// main.cc:6:10: error: call to implicitly-deleted copy constructor of 'std::basic_fstream<char>'
//    auto f = std::fstream{"foo.bar"};
//         ^   ~~~~~~~~~~~~~~~~~~~~

4
不应该有任何区别。如果我没记错的话,这是一个 libstdc++ 的 bug,因为它没有为所有流派生类型之一实现移动特殊成员函数。这是错误报告,根据 JonathanWakely 的说法,在 gcc5.0 中已经修复了。 - Praetorian
1
此外,在我看来,不要太过于字面理解“几乎总是自动”的含义。写成 auto f = std::fstream{"foo.bar"}; 看起来有点傻。直接使用 std::fstream f{"foo.bar"}; 即可。 - Praetorian
1
这里使用auto是没有意义的。你已经命名了类型,而且auto也没有什么特别之处,它遵循模板参数推导的规则。唯一的例外是在推导出std::initializer_list的情况下,但这里并不存在这种情况。 - user3920237
2个回答

3
我猜你在使用 libstdc++。目前它在这方面不符合标准,即尽管应该有移动构造函数,但 iostream 尚未具备。这将在版本 5 中得到修复:

运行时库(libstdc++)

...

完全支持 C++11,包括以下新功能:

可移动和可交换的 iostream 类;

来自版本 5 更改日志

2

auto推导和复制省略与此无关;你的代码与以下代码相同:

std::fstream f = std::fstream{"foo.bar"};
std::unique_ptr<int> i = std::unique_ptr<int>{new int};

在这两种情况下,都指定了一个复制/移动操作,这意味着如果有可用的移动构造函数则使用移动构造函数,否则使用复制构造函数。
正如您所说,即使在实践中复制/移动将被省略,标准也要求代码符合标准要求而不包括省略。 (这是为了确保正确的代码不会依赖于优化决策而神秘地编译,然后无法编译等。)
显然,C++11规定 fstream 应该有一个移动构造函数,但您的实现实际上尚未实现它。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接