2

a を返す関数を考えてみましょう。そのため、その定義でType*a を割り当てることができるように見えTypeますが、確かなことはわかりません (多くの関数があり、それらの定義を読む時間がありません)。

返されたポインタを削除する必要があるかどうかをどのように判断できますか? たとえば、これは次のタイプです。

struct MyStruct
{
    MyStruct(void) { cout << "Created.\n"; }
    ~MyStruct(void) { cout << "Deleted.\n"; }
};

そして、これは関数です:

MyStruct* Func1(void)
{
    return (new MyStruct());
}

Func1 はポインターを割り当てましたが、後でその割り当てを解除する必要があります。deleteしかし、おそらく定義は別のものであり、ポインターはdであってはなりません。

私の質問は、ポインタを削除するかどうかをどのように判断できますか? たとえば、ポインターが静的である可能性がありますか?

MyStruct* Func2(void)
{
    static MyStruct* ms = &MyStruct();
    return ms;
}

このポインタの割り当てを解除すると、プログラム全体がクラッシュします。

前もって感謝します。

4

4 に答える 4

8

これをプログラムで確認する方法はありません。1 プログラマーとして、何を削除する必要があり、何を削除する必要がないかを認識する必要があります。

より一般的に言えば、C++ で生のポインターを渡すことがしばしば嫌われる理由の 1 つがこれです。 スマート ポインターは、動的に割り当てられたメモリを管理するためによく使用されます。


1. 少なくとも、プラットフォームに依存しない堅牢な方法ではありません。

于 2012-07-21T09:59:16.210 に答える
7

返されたポインタを削除する必要があるかどうかをどのように判断できますか?

それはできません。これが、生のポインターを使用してメモリを管理することが非常に悪い考えである理由の 1 つです。オブジェクトを削除する必要がある場合は、スマート ポインターを使用して常に自動的に削除する必要があります。

これには、例外がスローされた場合でも、動的オブジェクトが終了すると常に削除されるという利点もあります。

std::unique_ptr<MyStruct> Func1()
{
    return std::unique_ptr<MyStruct>(new MyStruct);
}

void do_something()
{
    auto thing = Func1();
    do_something_with(thing);

    // The object is automatically deleted here
    // even if the function threw an exception.
}

適切に設計されていないライブラリを、削除する必要があるかどうかに関係なく関数が返すポインタで使用せざるを得ない場合は、ドキュメントを読むか、より良いライブラリを見つけるしかありません。削除が必要なポインターをすぐにスマート ポインターに割り当てて、少なくとも例外の安全性を確保することをお勧めします。

于 2012-07-21T10:09:00.893 に答える
1

事実:APIのドキュメントを読む時間がない場合は、バグが発生する可能性があります。

関数は常に多くの仮定を行い、すべてが異なるメカニズムによって強制されるという原則に帰着します。

  1. 一部は、通常は型を介して、コンパイラによって自動的に適用されます。たとえば、関数が特定の引数に書き込めると想定する必要がある場合、その型は非constになり、const引数を渡すとコンパイラエラーが発生します。これはバグを防ぐための最良の方法です。スマートポインターを返すことは、ポインターの所有権に対するコンパイラーの強制を提供する方法であるため、ドキュメントは必要ありません。これが、テンプレートまたは基本クラスよりもテンプレートまたは基本クラスを好む理由void*です。
  2. いくつかは、一般的な慣行または慣習によって暗示されています。繰り返しになりますが、これは、関数の仮定に準拠するためにドキュメントを読む必要がないことを意味します。これは、有能なプログラマーには明らかなはずだからです。たとえば、C ++関数がグリッドの行または列を要求する場合、0ベースであると期待できます。これは慣例です。または、あなたの場合、関数が参照を返す場合は、慣例により、呼び出し元がオブジェクトを削除してはならないことを意味します。
  3. それでも、文書化を除いて、多くの仮定を強制することはできません。たとえば、関数が境界チェックを実行するのか、NULLポインターを受け入れるのかを知ることはできません。API開発者として、可能であればこれを避ける必要がありますが、それに直面したときは、ドキュメントを無視することはできません。

C ++開発者として、私たちは可能な限り#1を使用するように努めていますが、他の開発者を完全に回避することはできません。

于 2012-07-21T10:32:29.190 に答える
0

Mike と Oli に完全に同意しますが、1 つだけ追加します。ライブラリが適切に作成されている場合、関数によって返されるポインターの所有者が正確にいつであるかを指摘するために使用される標準がおそらくあります (つまり、削除する必要があります)。 . これは、名前付けによって行うか、関数が特定のクラス/名前空間に属している可能性があります。その場合、それぞれの関数の定義を読むことを避けることができます。

于 2012-07-21T10:22:31.323 に答える