7

我想我会直接进入它并从代码开始:

#include <iostream>
#include <fstream>
#include <string>

class test : public std::ofstream
{
    public:
        test(const std::string& filename) { this->open(gen_filename(filename)); };
        test(const test&) = delete;
        //test(test&& old) = default; // Didn't compile
        test(test&& old) {};
    private:
        std::string gen_filename(const std::string& filename) 
        { return filename + ".tmp"; }
};

int main()
{
    auto os = test("testfile");
    os << "Test1\n";
    os << "Test2\n";
}

基本上,我需要返回一个 ofstream。当然,你不能复制 ofstream,所以我在类测试中摆弄了代码,我得到了上面的编译和工作,就像你期望的那样(在 gcc 4.5 上)。

但我有一种不好的感觉,这只是因为我的编译器在“auto os = test()”上做了“返回值优化”(RTO)。确实,如果修改为以下内容:

int main()
{
    auto os = test("testfile");
    os << "Test1\n";
    auto os2 = std::move(os);
    os2 << "Test2\n";
}

我不再在输出中同时得到 Test1 和 Test2 。

问题是,“test”类是不可复制的,因此 ofstream 不可能被复制。我只是希望能够从函数中返回它。我似乎可以用 GCC 做到这一点。

我宁愿不要取消引用指向分配的流的堆的智能指针,也不要重新打开文件,因为它目前可以在不做这些事情的情况下工作。我只是觉得我的方法有点“不标准”,所以用标准的方式来做我所描述的事情会很棒。

4

3 回答 3

16

我将在这里回答我自己的问题:

GCC C++0x 库功能页面中,查看第 27.9 项,内容如下:

27.9 - 基于文件的流 - 部分 - 缺少移动和交换操作

我想这可能是我在使用 gcc 时遇到的问题。

于 2011-01-31T01:36:42.370 回答
2

问题在于:

test(test&& old) {};

test这使您可以从 rvalue构造一个新的test,是的,但是它没有说明您的基础,它只是默认构造的(没有打开的文件)。你想要的是这样的:

test(test&& old) : std::ofstream(std::move(old)) {};

这会将流从old基础移入。

于 2011-01-28T07:40:17.243 回答
0

调用者是否需要知道您正在返回 a ,或者返回 a并让调用者将其包装在流中ofstream更有意义?streambuf

于 2011-01-28T08:21:08.603 回答