-1

作成したオブジェクトを指す変数があるとします。この例では、ランクとスーツの2つのメンバーを持つカードを表すオブジェクトがあるとします。

次に、作成したオブジェクト構造を初期化したとしましょう。これで、ランクとスーツのカードオブジェクトができました。

私の質問は、私が作成したこのカードオブジェクトを返す関数が必要な場合はどうなりますか?次のようなことをしたいです:

Card* playerCard = foo()

playerCardがカードオブジェクトを指していることは知っていますが、これはfoo()がカードオブジェクトも返す必要があることを意味しますか?この問題に対する別のアプローチはありますか?

基本的に、関数でカードを生成する必要があります。playerCardは、生成されるカードと同じである必要があります。オブジェクトを返すことが問題への最も簡単なアプローチであるかどうかはわかりません。そのため、別の解決策があるかどうかも尋ねています。

助けてくれてありがとう!

4

4 に答える 4

7

悪い方法から良い方法へと徐々に進んでいきます。

まず、これは間違った方法です。

Card* foo() {
  Card c;
  return &c;
}

絶対にしないでください。はCard c最後に破棄されるfooため、返すポインタは無効なオブジェクトを指しています。

あなたはこれを行うことができます:

Card* foo() {
  return new Card();
}

によって作成されたカードにnew Card()は動的な保存期間があるため、の終わりに破棄されることはありませんfoo。したがって、返されたポインタはまだそのカードを指しています。その後、ポインタを使用して安全を確保できます。

ただし、これには別の欠点があります。電話をかける人にはわかりませんが、メモリリークがないことを確認するために、返されたポインタを処理するfoo責任があります。delete代わりに、スマートポインターを使用して、呼び出し元に所有権を明確に渡すのが最善です。

std::unique_ptr<Card> foo() {
  return std::unique_ptr<Card>(new Card());
}

ただし、動的割り当てがまったく必要ない場合は、さらに優れています。を返しCard、関数からコピーしてみませんか?あなたはそのようにそれを行うことができます:

Card foo() {
  return Card();
}

次に、ポインタに割り当てる代わりに、次のように関数を呼び出します。

Card c = foo();

もちろん、これはこれを許可する要件によって異なります。多態的に使用したい場合Card*は、ポインタアプローチの1つを使用する必要があります。Cardそうしないと、派生物をスライスすることになります。

于 2013-03-26T21:19:17.143 に答える
1

オブジェクトではなく、そこにあるオブジェクトへのポインタを返します。

ここでの問題が正確にわからないので、完全な例を示します。

struct card {int rank; int suit};

card make_a_card() {
   return card{10,3};
}

int main() {
    card a_card = make_a_card();
    // a_card == card{10,3}
}

関数から生のポインタを返したいと思うことはめったにありません。速度には必要ありません(実際、RVOと移動セマンティクスのおかげで、実際には遅くなる可能性があります)。したがって、ランタイムポリモーフィズム(つまりファクトリメソッドの場合)を除けば、そうする理由はほとんどありません。

于 2013-03-26T21:19:28.807 に答える
0

ポインタを返したい場合は動的メモリ割り当てを使用できます。そうしないと、実行後にポインタが何も指さなくなりますfooダングリングポインタを参照)。

Card* foo() {
    Card* ret = new Card(...);
    ...
    return ret;
}

上記のコードの別のバージョンはstd::unique_ptr、標準ライブラリから使用して、動的に割り当てられたポインターを返していることをコードのクライアントプログラマーに明確にします。これはスマートポインターであるため、スコープの最後で自動的に割り当てを解除します(呼び出し側ブロックにコピーされるため、関数の最後ではありません)。

それ以外の場合、オブジェクト/構造体のコピーに費用がかからない場合は、値で返すことができ、コピーが作成されます。

Card foo() {
    Card ret(...);
    ...
    return ret;
}
于 2013-03-26T21:18:33.507 に答える
0

関数foo()がすでに作成されているCardオブジェクトへのポインターを返す場合、それにCardポインターを割り当てることは問題なく機能するはずです。ただし、コピーなどではなく、同じカードを効果的に渡すことを覚えておくことが重要です。

于 2013-03-26T21:19:14.833 に答える