0

エラー処理は、C++ コンストラクターでの課題です。いくつかの一般的なアプローチがありますが、そのすべてに明らかな欠点があります。たとえば、例外をスローすると、コンストラクターの早い段階で割り当てられたリソースのリークが発生する可能性があり、エラーが発生しやすいアプローチになります。静的init()メソッドを使用することも一般的な解決策ですが、RAII の原則に反します。

このテーマを研究していると、この回答とブログで という名前の C++17 機能の使用を提案していることがstd::optional<>わかり、有望であることがわかりました。ただし、この種のソリューションには根本的な問題があるようです。ユーザーがオブジェクトを取得すると、デストラクタが即座にトリガーされます。

問題を説明する簡単なコード例を次に示します。私のコードは上記のソースに基づいています

class A
{
public:
    A(int myNum);
    ~A();
    static std::optional<A> make(int myNum);
    bool isBuf() { return _buf; };
private:
    char* _buf;
};

std::optional<A> A::make(int myNum)
{
    std::cout << "A::make()\n";
    if (myNum < 8)
        return {};
    return A(myNum);
}

A::A(int myNum)
{
    std::cout << "A()\n";
    _buf = new char[myNum];
}

A::~A()
{
    std::cout << "~A()\n";
    delete[]_buf;
}

int main()
{
    if (std::optional<A> a = A::make(42))
    {
        if (a->isBuf())
            std::cout << "OK\n";
        else
            std::cout << "NOT OK\n";

        std::cout << "if() finished\n";
    }
    std::cout << "main finished\n";
}

このプログラムの出力は次のようになります。

A::make()
A()
~A()
OK
if() finished
~A()

その後、2 回削除しようとしたため、(少なくとも Visual C++ 環境では) 実行時エラーが発生しましたa->_buf

coutこの問題が非常に複雑なコードをデバッグしていることがわかったので、読者の便宜のために使用しましたが、問題は明らかです - のreturnステートメントA::make()はオブジェクトを構築しますが、それはA::make()スコープの終わりであるため、デストラクタが呼び出されます。ユーザーは、オブジェクトが初期化されていることを確認します (どのようにメッセージが表示されたかに注意して"OK"ください)。実際には、オブジェクトは破棄されています。if()maina->~A()

それで、私はこれを間違っていますか?コンストラクターでの for エラー処理の使用std::optionalは一般的です。前もって感謝します

4

1 に答える 1