1

私はC++に切り替えるJavaプログラマーです。クラス内のデータのリストがあります。クラス変数に格納されているリストの内容を返し、新しいリストを生成してクラス変数に格納し、空のリストに新しいデータを追加できるようにします。私はそれを行う方法を知っていると思いますが、私は参照とc ++メモリ管理に不慣れであり、後で愚かなメモリリークを望んでいないので再確認したいと思います。(実際のコードを簡単にコピーすることはできないので、書き直しているだけです。何かを間違って入力した場合はご容赦ください)。

正しい構文は次のようになると思います。

//mylist is typedef of a list type
mylist& temporaryList=classList;
classList=myList();
return classList;

この構文は正しいですか?また、返された変数またはclassList変数のいずれかをいつでも解放することを心配する必要がありますか、それともRIAAがすべてを処理してくれますか?

こんなに簡単な質問をしてすみませんが、私の仮定を確認していただきありがとうございます。

4

3 に答える 3

2
mylist& temporaryList=classList;

tempraryList参考です。変更するclassListと、それも変更されます。これを試して:

mylist tempraryList = classList;

これにより、mylistのコピーコンストラクタがコピーされ、他のコンストラクタをエイリアスするのではなく、新しいコンストラクタが作成されます。


return classList;

これは、新しいリストであると決定したものを返します。戻りたいtemporaryList。ただし、参照によって返されないようにしてください。temporaryListスコープ外になり(スタックに割り当てられているため、それ自体がクリーンアップされ)、参照がぶら下がってしまうためです。

同様に、通常、デフォルトのコンストラクターの結果を割り当てるのではなく、クラスresetは別のオブジェクトのオーバーヘッドなしでそれを行うための一種の関数を提供する場合があります。

于 2012-06-16T00:22:43.850 に答える
1

@chrisが参照を使用しているという問題があると指摘しているように、参照には実際のオブジェクトをほとんどまたは無料でエイリアスするという優れた機能がありますが、あなたの場合は、メンバーリストをリセットするとリセットされることを意味しますプログラム内の唯一のリスト。

@chrisも指摘しているように、コードに対する簡単な修正は、リストをコピーしてから元のコードをリセットすることです。

mylist getAndClear() {
   mylist temporaryList=classList;    // make a copy
   classList=myList();                // reset the internal
   return temporaryList;              // return the **copy**
}

現在、このアプローチの問題は、元のリストがすぐに破棄されることがわかっている場合に、コピーのコストが発生することです。コピーアンドスワップイディオム(*)を使用すると、そのコストを回避できます。

mylist getAndClear(){mylist tmp; //空のswap(tmp、classList); //コンテンツをスワップします。classListは空になります//tmpはデータを保持しますreturntmp; }

mylistこれは、それがであると想定していstd::listます。そうでない場合は、必ず実装してくださいswap(または、C ++ 11のmoveコンストラクターでは、効率的に有効になりますstd::swap)。


(*)これは、コピーアンドスワップのイディオムを直接適用しているようには見えないかもしれませんが、実際には、適用される変更がリストをクリアしているところです。コピーを実行し、コピーに変更を適用し(この場合、変更によってコピーが空になるため、コピーは回避されます)、操作が正常に完了したら、内容を交換します。

于 2012-06-16T01:21:38.257 に答える
0

chrisは、メンバー関数を使用して次のようにオブジェクトをリセットまたはクリアすることに言及しています。

mylist tmp = classList;
classList.clear();
return tmp;

しかし、そもそもコピーを避けることで、通常はさらにうまくいくことができます。

mylist tmp;
std::swap(tmp,classList);
return tmp;

また、返された変数またはclassList変数のいずれかをいつでも解放することを心配する必要がありますか、それともRIAAがすべてを処理してくれますか?

どこかにいdeleteない限り、リソースを用意する必要はありません。newまた、使用する場合はnew、スマートポインターも使用する必要があります。そうすれば、delete何もする必要がなくなります。

JavaからのC++について理解する最も重要なことの1つは、C++オブジェクトはデフォルトで値に似たオブジェクトであるということです。あれは:

class A {
    bool bar_called;
public:
    A() : bar_called(false) {}
    void bar() { bar_called = true; }
    bool has_bar_been_called_on_this_object() { return bar_called; }
};

void foo(A a) {
    a.bar();
}

int main() {
    A a;
    foo(a);
    std::cout << a.has_bar_been_called_on_this_object() << '\n';
}

出力は、バーが呼び出されていないaことを示します。Javaはポインタを使用しますが、非表示にしようとします。したがって、C ++でポインターを理解すると、物事がより理にかなっているはずです。そうすれば、ポインターを使用しない方法を理解できるようになります。

Object o = new Object(); // Java hides the fact that o is a pointer to an Object, but fails to hide the consequences
Object b = o; // b is a pointer to an object, the same Object o points to.

// Equivalent C++
Object *o = new Object();
Object *b = o;

提示したC++コードから判断すると、Javaでは、次のような質問をします。

mylist tmp = classList;
classList = new mylist();
return tmp;

C++での同等のものは次のようになります。

mylist *tmp = classList; // classList is a pointer to a new'd up list.
classList = new mylist();
return tmp;

ただし、これは理想的なC++ではありません。C ++では、通常、ポインターは使用しません。使用する場合は、スマートポインターを使用します。

std::shared_ptr<mylist> tmp = classList; // classList is a std::shared_ptr<mylist>
classList = std::make_shared<mylist>();
return tmp;

また

std::unique_ptr<mylist> tmp = std::move(classList); // classList is a unique_ptr
classList = std::unique_ptr<mylist>(new mylist()); // careful here, don't go calling a bunch of functions inside the mylist initializer, it's dangerous for reason beyond the scope of this post
return tmp;

しかし、C ++の方法は、実際にはポインターを完全に回避することです。

mylist tmp; // classList is not a pointer at all
std::swap(tmp,classList); // the values of classList and tmp are swapped
return tmp; // tmp is returned by value, tmp has the same value as classList, but is not the same object, tmp and classList are objects, not pointers to objects as they are in Java or in the above C++ examples.
于 2012-06-16T01:14:56.237 に答える