5

例:

Class *_obj1;
Class *_obj2;

void doThis(Class *obj) {}

void create() {
    Class *obj1 = new Class();
    Class obj2;

    doThis(obj1);
    doThis(&obj2);

    _obj1 = obj1;
    _obj2 = &obj2;
}

int main (int argc, const char * argv[]) {

    create();

    _obj1->doSomething();
    _obj2->doSomething();

    return 0;
}

これにより、2 つのオブジェクトが作成され、それらへのポインターが作成され、次に main() がそれぞれのメソッドを呼び出します。Class オブジェクトは char* を作成し、C 文字列 "Hello!" を格納します。初期化; ~Class() デアロケータはメモリを解放します。doSomething() メソッドは、printf() を使用して "buff: %s" を出力します。十分に単純です。これを実行すると、次のようになります。

ディロック
バフ: こんにちは!
バフ:¯ø_ˇ

明らかに、スタック オブジェクトはここでは機能しません。関数が終了するとき、ポインター _obj2 がスタック内の場所を指していることは明らかです。これが、以前の質問でヒープ オブジェクトを使用した理由です。人々は私に「ばかげている」と言っていました。

したがって、最初の質問は、create() の終了後に割り当てが解除されないように、スタック オブジェクト (obj2) をヒープ オブジェクトに変換するにはどうすればよいかということです。多くの人がそうしてきたように、傲慢な「あなたは間違ったことをしている」ではなく、率直な答えが欲しい. この場合、スタックオブジェクトは機能しないため、ヒープオブジェクトが唯一の方法のようです。編集: また、スタック オブジェクトに変換することも同様に役立ちます。

2 番目の質問: ヒープ オブジェクトが「間違っている」具体的な例は、演算子vector<string>*を使用して新しいオブジェクトを作成することでした。STL オブジェクトの動的割り当てが間違っている場合、正しい方法は何ですか? それらをスタックオブジェクトとして作成すると、すぐに割り当てが解除されるため失敗することは明らかですが、それらを動的に割り当てるとヒープが破損する可能性があると(非常に高いランクのメンバーから)言われました。それで、それを行う正しい方法は何ですか?new

4

7 に答える 7

9

したがって、最初の質問は、create() の終了後に割り当てが解除されないように、スタック オブジェクト (obj2) をヒープ オブジェクトに変換するにはどうすればよいかということです。ストレートな答えが欲しいのですが、

率直な答えは、スタックとヒープの間でオブジェクトを「変換」することはできません。他の人が指摘したように、他の空間に存在するオブジェクトのコピーを作成できますが、それだけです。

2 番目の質問: ヒープ オブジェクトが「間違っている」具体的な例は、new 演算子を使用して新しい vector* を作成することでした。STL オブジェクトの動的割り当てが間違っている場合、正しい方法は何ですか? それらをスタックオブジェクトとして作成すると、すぐに割り当てが解除されるため失敗することは明らかですが、動的に割り当てるとヒープが破損する可能性があると(非常に高いランクのメンバーから)言われました。

STL オブジェクトを動的に割り当てても、ヒープが破損することはありません。(どこで聞いたかもわかりません。)

スタックに割り当てられた STL オブジェクトを作成した関数の外部で使用したい場合、オブジェクトが存在するスタック空間はそれを作成した関数内でのみ有効であるため、使用できません。

ただし、オブジェクトのコピーを返すことはできます。

std::vector<char> SomeFunc()
{
    std::vector<char> myvector;
    // myvector.operations ...
    return myvector;
}

ただし、私が言ったように、これは元のオブジェクト自体ではなく、オブジェクトのコピーを返します。オブジェクトを含むスタックは関数が戻った後に巻き戻されるため、これは不可能です。

別のオプションの 1 つは、関数が操作するオブジェクトへの参照/ポインターを呼び出し元に渡させることです。これが特定のシナリオで意味がある場合:

void SomeFunc(std::vector<char>& destination)
{
    // destination.operations ...
}

void AnotherFunc()
{
    std::vector<char> myvector;
    SomeFunc(myvector);
}

ご覧のとおり、まだすべてをスタックに割り当てており、コピー コンストラクターに依存してオブジェクトのコピーを返すことによる (場合によっては結果的な) オーバーヘッドを回避できます。

于 2011-02-20T18:03:00.550 に答える
5

したがって、最初の質問は、create() の終了後に割り当てが解除されないように、スタック オブジェクト (obj2) をヒープ オブジェクトに変換するにはどうすればよいかということです。

この行:

_obj2 = &obj2;

への変更:

_obj2 = new Class(obj2);  // Create an object on the heap invoking the copy constructor.

多くの人がそうしてきたように、傲慢な「あなたは間違ったことをしている」ではなく、率直な答えが欲しい.

それはあなたが得ることができるのと同じくらいまっすぐな答えです。明らかに、あなたは C++ に慣れていないので、クラス "Class" (ちなみにひどい名前) の定義でおそらくいくつかの間違いを犯したため、これは意図したとおりに機能しないと確信しています。

また、スタック オブジェクトに戻すことも同様に役立ちます。

class obj3(*_obj2);  // dereference the heap object pass it to the copy constructor.

2 番目の質問: ヒープ オブジェクトが「間違っている」具体的な例は、new 演算子を使用して新しい vector<string>* を作成することでした。STL オブジェクトの動的割り当てが間違っている場合、正しい方法は何ですか?

ベクトルを動的に割り当てるのはなぜですか。ローカルで作成するだけです。

std::vector<std::string> funct()
{
    std::vector<std::string>   vecString;
    // fill your vector here.

    return vecString;  // Notice no dynamic allocation with new,
}

new/delete を使用することは、C のように C++ を使用することです。読む必要があるのは、スマート ポインターです。これらは、オブジェクトの寿命を制御し、範囲外になるとオブジェクトを自動的に削除するオブジェクトです。

std::auto_ptr<Class>   x(new Class);

ここで、x は (auto_ptr 型の) スマート ポインターであり、スコープ外に出るとオブジェクトが削除されます。ただし、呼び出し元の関数に auto_ptr を返すことができ、関数から安全に転送されます。実際にはそれよりもはるかに複雑で、本が必要です。

それらをスタックオブジェクトとして作成すると、すぐに割り当てが解除されるため、明らかに失敗します。

範囲外になると割り当て解除されます。

しかし、動的に割り当てるとヒープが破損する可能性があると (再び、非常に高位のメンバーから) 言われました。

やり方を間違えると. あなたの知識を考えると、これは非常に可能性が高いです。ただし、クラスの定義を提供していないため、確認するのは困難です。

それで、それを行う正しい方法は何ですか?

  1. スタック オブジェクトを使用する理由を学ぶ
  2. スマート ポインターとは何かを学びます。
  3. スマート ポインターを使用してオブジェクトの寿命を制御する方法を学びます。
  4. さまざまな種類のスマート ポインターについて学習します。
  5. 関心の分離とは何かを調べてください (この基本原則に従っていません)。
于 2011-02-20T18:11:40.973 に答える
1

新しいヒープ オブジェクトをコピーして構築するか ( Class * foo = new Class(obj2))、スタック オブジェクトをヒープ オブジェクトに割り当てる( ) 必要があります*obj1 = obj2

于 2011-02-20T18:00:51.107 に答える
0

唯一の方法は、オブジェクトをコピーすることです。

宣言を次のように変更します。

Class _obj2;

割り当てます:

_obj2 = obj2;

于 2011-02-20T17:59:01.403 に答える
0

スタック オブジェクトは create 関数内で作成され、関数のスコープから出るとすぐに割り当てが解除されます。ポインターが無効です。

次のように変更Class* obj2してClass obj2、オブジェクトを割り当てる (つまり、コピーする)ことができます。obj2 = obj2;

于 2011-02-20T18:00:46.440 に答える
0

スタック変数のアドレスを取得しても、魔法のようにヒープに転送されるわけではありません。クラスに適切なコピー コンストラクターを作成し、 を使用する必要があります_obj2 = new Class(obj2);

STL コンテナーに関しては、とにかくデータをヒープに割り当てますが、なぜコンテナー自体をヒープに割り当てたいのでしょうか? それらを必要な限り存続させるスコープに入れます。

于 2011-02-20T18:02:55.560 に答える
0

「関数内で作成されたオブジェクトを返すにはどうすればよいですか?」と本当に尋ねようとしていると思います。いくつかの有効な方法があります。

  • ヒープに割り当ててポインターを返す
  • 自動変数を使用し、ポインターではなくその値を返します (コンパイラーはそれをコピーします)。
  • 呼び出し元がポインターまたは参照パラメーターによってストレージを提供し、そこにオブジェクトを構築できるようにします。
于 2011-02-20T18:05:41.643 に答える