3

コードでauto_ptrを使用しようとしていますが、どうやら問題が発生しています。

auto_ptr<ClassType> Class(s.Build(aFilename)); //Instantiation of the Class object
int vM = s.GetM(Class);
int vS = s.Draw(Class);

奇妙なことに、Classのインスタンス化後、Classオブジェクトが存在するため、s.GetModelMean(Class)を呼び出すことにより、Classは空になりません。ただし、関数GetMを終了すると、クラスは空になり、使用できなくなります。関数Drawを呼び出すとクラッシュが発生します。

関数を次のように宣言しました。

int GetM(auto_ptr<ClassType> aM); 

クラスが破壊されたようですが、理由がわかりません...

4

4 に答える 4

6

関数の引数としてauto_ptrを指定しないでください。どちらか:

int GetM(const auto_ptr<ClassType>&)

また

int GetM(ClassType&)

また

int GetM(ClassType*)

(constを使用する場合もあります-それを使用して何をしているかによって異なります)。最初に同じ方法で呼び出し、2番目の関数を次のように呼び出します。

int vM = s.GetM(*Class.get())

星のない最後。

理由は次のとおりです。GetMはauto_ptr(Classオブジェクトではない)をコピーし、戻ったときにauto_ptrを破棄します。auto_ptr(スコープポインターまたは一意のポインター-参照カウンターではありません!)は、クラスを破棄します。

とにかく:auto_ptrは非常に壊れています。可能な限り(コンパイラはすでにC ++ 11のいくつかの小さな部分をサポートしています)、std::unique_ptrとstd::shared_ptrを使用します(最後のものは参照カウントを行います)。unique_ptrを使用すると、そのように操作することはできません(コピーは許可されていないため、imhoの方がはるかに理にかなっています)。

于 2012-07-12T06:35:59.387 に答える
1

auto_ptrには、ソースオブジェクトを混乱させる「魔法の」コピーコンストラクタがあります。引数を値で関数に渡すことにより、コピーコンストラクターの呼び出しをトリガーし、元のauto_ptrを何も指さない状態のままにします。

于 2012-07-12T06:32:35.300 に答える
0

呼び出す理由

int GetM(auto_ptr<ClassType> aM); 

与えられたオブジェクトを破壊するのは、オブジェクトをauto_ptrコピーするときにかなり驚くべき振る舞いをするということです。宛先オブジェクトを変更するだけでなく、ソースオブジェクトも変更します。あなたがするならしなさい

std::auto_ptr<int> y = x;  // modifies x *and* y

に格納されているポインタxに移動しますyxnullに設定されます)。

これは、std::auto_ptr値をコンテナに渡したり、コンテナに保存したりするのに非常に不適切であることを意味します(コンテナはオブジェクトを内部でコピーする傾向があるため)。たとえば、コードの例外を安全にするために、スコープを終了するときにオブジェクトが確実に破棄されるようにするのが適切ですだから何かを持っている

void f() {
  std::auto_ptr<int> x = new int;
  ...
  // no need to delete anything, destroying 'x' will delete
}

または

class Widget {
public:
  Widget() : m_myData( new int ) { }

private:
  Widget(const Widget &other); // disabled
  void operator=( const Widget &other ); // disabled

  std::auto_ptr<int> m_myData;
};

実際には問題なく、コードを簡素化できます。

所有権を持つstd::auto_ptr手段を持つ。GetMしたがって、特定のケースでは、単純なポインタを使用するように署名を調整することをお勧めします。

于 2012-07-12T06:44:16.233 に答える
0

auto_ptrAをBに「コピー」するたびに、Bがオブジェクトを取得し、Aがクリアされるように、ちょっとしたトリックを使用します。これを使用して、所有権の受け渡しのセマンティクスを非常に明確に宣言できます(出典:ScottMeyersおよびAndreiAlexandrescusの本。ところで、詳細を知りたい場合は、Effective C ++を参照してください)。

もちろん、可能であれば、非推奨のように、unique_ptrC ++ 0xまたはBoostの代わりに(ベクトルに入れることができます!)を使用する必要があります。auto_ptrauto_ptr

トリックの詳細に興味がある場合は、マジックコピーコンストラクターがないことを知っておいてください。コピーコンストラクタはまったくありません。コピーコンストラクターはconst参照を取り、コピーされたオブジェクトをクリアすることはできません。だからあなたが書くとき

std::auto_ptr<A> a1(new A);
std::auto_ptr<A> a2(a1);

a1は最初に一時オブジェクトにキャストされます。キャスト演算子は非定数参照を取得し、a1をクリアします。次に、a2はこの一時オブジェクトによって初期化されます。

于 2012-07-12T07:03:34.643 に答える