関数が新しいポインタを返すことを示す標準的な方法はありますか?


8

クラスが所有するオブジェクトの構築を別の関数に委任したい場合があります。何かのようなもの

Vertex* new_vertex(const Options& options) {
  // do stuff...
  return new Vertex(...);
}

この関数は、を所有するクラス内でのみ使用することを目的としていVertexます。明らかに、この関数はメモリリークを引き起こす混乱を引き起こす可能性があるため、できるだけ明確にしたいと思います。そのような関数の命名規則はありますか?


11
はい。 // TODO: Fix allocation of raw pointer.
Gort the Robot、2015

3
@StevenBurnap問題が解決しない限り、「修正」という言葉は使用しません。
user253751 2015

1
「混乱」の懸念についての単なる発言。呼び出し側が返されたオブジェクトを適切に処理することも同様に重要です。スマートポインターはこれを(メモリ管理を継続的な精神的努力ではなく機械的な習慣にすることで)楽にすることができますが、呼び出し元が明確なポリシーやコーディング標準、または階層的な「オブジェクトの所有権」の概念を持っていない場合、最終的にはまだ問題が発生しています。場合によっては、ジュニアプログラマーがunique_ptrそのrelease()関数を呼び出してを回避し、古い方法のように生のポインターを使用することさえあります。
rwong 2015

1
@StevenBurnapなぜ単純にではないのです// FIXME: Allocation of raw pointerか?
トビアスキエンツラー2015

1
あなたの機能はそれを私にかなり明確にします。戻り値の型は、値または参照ではありません。どちらの場合も、メモリをクリアしようとすることは、本能的でない構文の問題です。関数が呼び出されるnew_vertexので、オブジェクトが新しく作成されたことがわかります。よりCreate_new_vertex明確にするためにそれを呼ぶことができます。あなたはスマートポインタせずにヒープメモリを管理するべきではないという考えについては、その中に真実見たことがない-あなたはヒープメモリを管理することができない場合は、実際にはせずに、それらを、あなたはヒープメモリを管理する一切の事業を得なかっましどちらかそれら!
Grimm The Opiner 2015

回答:


21

を返すunique_ptr

std::unique_ptr<Vertex> new_vertex(const Options& options) {
  // do stuff...
  return std::make_unique<Vertex>(...);
}

unique_ptr特定のオブジェクトを指すオブジェクトは1つだけです(Vertex*とにかく、キャストしてそれを悪用しない限り)。をコピーすることはできませんunique_ptr。移動するだけです。a unique_ptrが破棄された場合(そしてそこから移動されていない場合)deleteは、オブジェクトのsです。

make_unique新しいVertexを作成し、それをでラップしunique_ptrます。渡すmake_unique引数は、コンストラクタに渡す引数です。


4
これは役に立ちますが、実際には私の質問に答えられません。私はスマートポインターについて知っています。ユーザーが処理する必要がある生のポインターを返す関数の命名規則があるかどうかを知りたかっただけです。答えは「いいえ、ありません。絶対にやるべきではないので」でしょうか。
2015

3
@Shep関数を呼び出した人に、それが新しいオブジェクトを作成することを示したい場合は、それを行いますunique_ptr。なんらかの理由で名前にする必要がある場合、そうではないと思いますが、なぜ名前にする必要があるのですか?
user253751

8
@Shepの名前は具体的なものではなく、誰もが完全に無視できます。一方、型はコンパイラーによって強制されます。つまり、型を壊すにはかなりの労力が必要です。タイプのジョブを実行するために名前を送信しないでください。
ComicSansMS 2015

1
@Shep この場合、生のポインタを返すことに害はありません。このケースでは、作成者がライフタイムを管理するのは呼び出し側に任されているオブジェクトを作成しました。発信者は、必要な場合はいつでもスマートポインターに直接ドロップできます。
Grimm The Opiner 2015

1
@immibis:なぜあなたはのtemplate-argument-deductionをオーバーライドするのstd::make_uniqueですか?それは...冗長でエラーが発生しやすいunneccessarilyだ
デュプリケータ

2

関数が新しいポインタを返すことを示す標準的な方法はありますか?

いいえ、「標準的な方法」はありません(ただし、現在「ベストプラクティス」と見なされているAPI設計ポリシーがあります)。

このあいまいさ(「ポインターを返す関数が私にそれを実行してほしいと思うのは何ですか?」)があるため、現在は、戻り値の型を通じて有効期間と所有権のポリシーを課すことがベストプラクティスと見なされています。

<vertex pointer type> new_vertex(const Options& options);

<vertex pointer type>ことができますstd::unique_ptr(「new_vertexポインタを所有していない」)、またはstd::shared_ptr(「クライアントコードはポインタを所有していない」)、または何か他のもの、それは明らかに所有権の意味を定義している(例えば、Vertex const * const「クライアントコードに示すことになる読みますアドレスと値。ただし、どちらも変更しない/ポインタを削除しない」)。

一般に、生のポインタを返すべきではありません(ただし、「実用性が純粋さを上回る」場合もあります)。

TLDR:ベストプラクティスはありますが(yes)、標準的な方法はありません(言語では)。

編集

関数は、頂点を所有するクラス内でのみ使用されることを意図しています

クラスがVertexを所有している場合、次のように記述します。

class SomeClass // owns the vertex
{
    void do_stuff() // uses the vertex internally
    {
        init_vertex(); // see below
        assert(vertex.get());
        // use vertex as needed
    }
private:
    // "class owns the Vertex"
    std::unique_ptr<Vertex> vertex;

    // sets the internal vertex
    // function doesn't return a pointer of any kind
    void init_vertex(const Options& options); // or "reset_", "refresh_", 
                                              // or "make_" vertex,
                                              // if the pointer can change
                                              // throughout the lifetime
                                              // of a SomeClass instance
};

0

はい、これには何十もの「標準」があります

XKCD

推奨する答えunique_ptrはおそらく最良の答えですが、生のポインタを見る場合、誰もが独自の標準を開発しています。

一般的に言えば、新しいオブジェクトを意味する、create_____またはnew______そのalloc_____傾向がある関数。

しかしながら

あなたが行動を混ぜていると考えてください。これがオブジェクトの新しいインスタンスであるかどうかは、実際には気にしません。 気になるのは、呼び出し元がオブジェクトを破棄する責任があるかどうかです。 既存のオブジェクトの責任を引き継ぐ多くのAPIがあり、それらの関数は一致する命名スキームを必要とします。たぶんgive______

C ++から少し離れ
ても構わないのであれば... Objective-CがC ++に十分に似ていると考えて回答のソースになる場合、実際にはその言語で本当の答えがあります。Objective-Cは、参照カウントを使用してオブジェクトの寿命を管理します。彼らには、オブジェクトに対する責任が与えられているのか、それとも単に既存のオブジェクトへの参照が与えられているのかを説明する方法が必要でした。答えが間違っていると、参照カウントが間違ってオブジェクトが失われます。したがって、彼らはルールを作りました:返されたすべてのオブジェクトは他の誰かが所有しています(したがって、参照カウントを自分でインクリメントおよびデクリメントする必要があります)。これらの呼び出しは、メソッド名によって識別されました。alloc new copyまたはで始まるメソッドmutableCopy常に新しいオブジェクトを返しました。そこで、標準は言語によって強制されました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.