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をコピーすることはできないので、クラステストのコードをいじって、上記をコンパイルして期待どおりに動作させました(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 Library Featuresページで、項目 27.9 を見てください。

27.9 - ファイルベースのストリーム - 部分的 - 移動およびスワップ操作が欠落している

それはおそらく私がgccで抱えている問題だと思います。

于 2011-01-31T01:36:42.370 に答える
2

問題はこれにあります:

test(test&& old) {};

testこれにより、 rvalue からnew を構築できますがtest、ベースについては何も言いません。これは、デフォルトで構築されているだけです(開いているファイルはありません)。あなたが欲しいのはこれです:

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

ストリームをoldベースに移動します。

于 2011-01-28T07:40:17.243 に答える
0

呼び出し元は、あなたが を返していることを知る必要がありますか? それとも、 を返し、呼び出し元がそれをストリーム内にラップできるofstreamようにする方が理にかなっていますか?streambuf

于 2011-01-28T08:21:08.603 に答える