5

この方法でポインターを返す C++ チュートリアル サイトを少なくとも 5 つ見たことがあります。

int* somefunction(){
    int x = 5;
    int *result = &x;
    return result;
}

それは非常に悪い考えではありませんか?私のロジックは、返されたポインターの値はいつでも上書きできることを示しています。これが正しい解決策になると思います:

int* somefuntion(){
    int x = 5;
    int* result = new int;
    *(result) = x;
    return result;
}

次に、呼び出し元の関数をそのままにして、ポインターを削除します。それとも私は間違っていますか?

4

6 に答える 6

8

問題に対するあなたの直感は正しいです。UB はその結果です。ただし、提案されたソリューションは悪いです。「呼び出し元に削除を任せる」は非常にエラーが発生しやすく、お勧めできません。代わりに、意図した使用法を適切にカプセル化する所有クラスでそれを返します-できればstd::unique_ptr<int>

于 2012-06-30T15:37:32.830 に答える
6

はい、最初のオプションはダングリング ポインターを返し、未定義の動作につながります。2番目のオプションは正しいですが、次のように書くこともできます:

int* somefuntion(){
    return new int(5);
}

またはstaticメソッド内に変数を持ち、そのアドレスを返します。

于 2012-06-30T15:35:14.443 に答える
3

あなたの質問は、いくつかの異なる問題を 1 つにまとめています。実際には、ここでの主な問題は、その混合物が本当に必要かどうかです。

「ポインタを返す」ということ自体はありません。「ポインターを返したい」という理由だけで「ポインターを返す」わけではありません。ポインターを返すことは特定の理由で行われ、その理由によって、それがどのように行われ、適切に機能するために何をする必要があるかが決まります。

元の例では、ポインターを返す意味のある理由がないため、元の例は実際にはそれを示していません。単に返すことができるようですint

たとえば、ポインタは動的に割り当てられたオブジェクト (つまり、有効期間が言語のスコープ規則に従わないオブジェクト) へのポインタであるため、多くの場合、ポインタを返したいと思うでしょう。この場合のカジュアルな関係は逆方向に機能することに注意してください。動的オブジェクトが必要です -> ポインターを返す必要があります。そのように、その逆ではありません。あなたの例では、それを逆に使用しているようです: ポインターを返したい -> オブジェクトを動的に割り当てる必要があります。後者の推論には根本的な欠陥がありますが、予想以上に頻繁に使用されていることがわかります。

動的に割り当てられたオブジェクトが本当に必要な場合 (上で述べたように、主な理由は、言語のスコープベースの有効期間規則をオーバーライドすることです)、メモリの所有権の問題が問題になります。このメモリの割り当てをいつ解除できるか、または解除する必要があるか、および誰が割り当てを解除する必要があるかを知るには、排他的 (常に 1 人の指定された所有者) または共有 (参照カウントなど) 所有権スキームを実装する必要があります。これは生のポインタでも実行できますが、ライブラリが提供するさまざまなスマート ポインタ クラスを使用することをお勧めします。

しかし、多くの場合、非動的オブジェクト (静的または自動) へのポインターを返すこともできます。これは、これらのポインターの有効期間が、それらが指すオブジェクトの有効期間と同じかそれよりも短いと仮定すると、まったく問題ありません。

つまり、ポインターを返すという決定の背後にある理由は、C と C++ の間で実際には違いはありません。言語関連よりもデザイン/意図関連です。C++ は、ポインターを返すことを決めた後で作業を容易にするためのツールを提供するだけです。(これは、C++ プログラマーが隠しポインターを乱用するインセンティブとして機能することがあります)。

いずれにしても、これは実装しようとしている機能の問題です。それがわかれば、「ポインターを返す」必要があるかどうかについて適切な決定を下すことができます。最終的にポインターを返すことにした場合は、適切な戻り方法を選択するのに役立ちます。それがどのように機能するかです。後ろ向きに考えようとすると (「ポインターを返したいだけですが、まだ本当の理由はありません」)、学問的に役に立たない答えしか得られません。特定の状況。

于 2012-06-30T15:40:48.163 に答える
3

はい、最初の例は、システムが別の目的で再利用する可能性のあるメモリへのポインターを返すため、適切ではありません。2 番目の例の方が優れていますが、ポイントされているメモリを削除する責任がある関数の呼び出し元には明確ではないため、メモリ リークのリスクがあります。

このようなものが良いかもしれません:

std::unique_ptr<int> somefunction(){
    int x = 5;
    std::unique_ptr<int> result( new int );
    *result = x;
    return result;
}

このように、unique_ptr は、新しく作成したメモリの削除を処理し、潜在的なメモリ リークを排除するのに役立ちます。

于 2012-06-30T15:44:12.063 に答える
1

あなたが疑い、他の人が明らかにしたように、最初の方法は明らかに間違っています。C++ はシステム言語であり、これを実行したい状況がいくつかありますが (ほとんどのシステムでは、スタック上の特定の相対位置が返されます)、それはほとんど正しくありません。2 番目の方法は、はるかに正気です。

ただし、C++ ではどちらの方法も推奨されません。C++ の主なポイントの 1 つは、C のポインターだけでなく、参照と例外があることです。つまり、参照を返し、メモリ割り当てが失敗した場合に new がスタックに例外をスローできるようにします。

于 2012-06-30T15:44:33.953 に答える
0

メソッドの呼び出し後にポインターを削除することを忘れないでください。これは正しいことです。

于 2012-06-30T15:37:23.750 に答える