2

概要: 同じ型の 2 つのオブジェクトで「=」代入演算子にアクセスできないのはなぜstd::unique_ptr<Expression, std::default_delete<Expression>>ですか? コードでは型が記述されていますstd::unique_ptr<Expression>が、IntelliSense エラーでは前者に展開されます。

情報

IDE - Visual C++ 2010
OS の実行 - Windows Vista
ターゲット - C++11 の実装を使用しようとするコンソール アプリケーション

いくつかの背景

C++ の式エバリュエーターの例が提供されましたが、これは明らかに新しい標準に準拠しているようです。なぜなら、堅実なコードであるべきものがエラーを引き起こしているからです。VC++ がこの機能をサポートしていないためだと推測しています。私が得た最初のエラーは「make_unique」メソッドで、VC++は「識別子が存在しません」と言ったので、自分で実装しました

template<typename T>
std::unique_ptr<T> make_unique()
{
    return std::unique_ptr<T>(new T());
} // Basically just wrapping 'new'? Not sure why

オンラインでより良いものを見つけましたが、エラーが発生しました。これは ^ エラーを発生させません。...Args テンプレート パラメータを削除しただけです。次のような Expression クラスのセットがあります。

class Expression {
    virtual ~Expression() {}
};

class BinaryExpression : public Expression {
public:
     std::unique_ptr<Expression> lhs;
     std::unique_ptr<Expression> rhs;
     virtual char GetType() const = 0; // +,-,/,*
};
// Then MulExpression, DivExpression, PlusExpression, blah blah

ここでエラーが発生します。ParseAdditiveExpression() の戻り値の型は次のとおりです。

// expr, lhs, and rhs are all of the same type
std::unique_ptr<Expression>:
auto rhs = ParseAdditiveExpression();
auto expr = make_unique<MulExpression>(); // Tried using: std::unique_ptr<Expression> expr;
expr->lhs = lhs; // Trouble Makers
expr->rhs = rhs; // All produce
lhs = expr; // The same errors

エラーは次のとおりです。

1   IntelliSense: "std::unique_ptr<_Ty, _Dx> &std::unique_ptr<_Ty, _Dx>::operator=(const std::unique_ptr<_Ty, _Dx> &) [with _Ty=Expression, _Dx=std::default_delete<Expression>]" 
(declared at line 2352 of "C:\Program Files\Microsoft Visual Studio 10.0\VC\include\memory")
is inaccessible 
c:\users\s_miller47\documents\visual studio 2010\projects\_vc++\powercalc\mathparser.h  133

さて、これは「=」の正しいサイズの「const」と関係があるかもしれないと思いますが、関数の戻り値の型を変更して、戻り値の型の後に * または & を付けてみました。 expr->lhs に設定する前に値を参照 ('*') し、試してみました ('&')

では、オペレーターにアクセスできない場合、どうすれば修正できますか? 演算子を自分で定義する必要がありますか? (ナンセンス) さて、ここに完全なコードがあります: PasteBin ソース コード リンク

4

3 に答える 3

6

std::unique_ptr譲渡不可、コピー不可です。そのような割り当てを行いたい場合は、次を使用する必要がありますstd::move()

lhs = std::move(expr);
于 2012-09-04T11:08:43.447 に答える
5

のインスタンス化はstd::unique_ptrコピーできません。それらは移動することしかできません(したがって、「一意」です)。したがって、割り当てのために、ポインターを移動したいと言う必要があります。

lhs = std::move(expr);
于 2012-09-04T11:09:30.773 に答える
3

問題は、名前が示すように、unique_ptr が一意のポインターを維持することです。これが、autp_ptr が非推奨になった主な理由の 1 つです。代入内のポインターをコピーするのではなく、実際に「移動」しました。これは悪いことだと考えられています。"a=b" を実行すると、2 つのほぼ同一のオブジェクト "a" と "b" が期待されます。「b」が空になるとは思わないでください。

したがって、ポインターの一意性を維持するために、unique_ptr はいかなる形式のコピーも許可しません。

于 2012-09-04T11:09:10.813 に答える