0

C/C++ では、ポインターを返すことができます。

int* returnpointer() {
    int c = 1;
    int *d = &c;
    return d;
}

呼び出し元関数で使用できるようにします。

int* p = returnpointer();

これは、最も自然な意味を成すので、私が最も慣れているスタイルです。

では、通常の状態では上記で十分な場合、なぜ C/C++ はアドレスを返す言語機能を提供するのでしょうか? すなわち:

int& returnpointer() {
    int c = 1;
    int *d = &c;
    return *d;
}

呼び出し元を介して呼び出されます:

int* p = &returnpointer();

私が前者に精通していることを考えると、前者があまり適していない後者の機能はありますか?

PS: 関数がスタックを終了すると、存在しなくなった変数を指すポインタが含まれる可能性があるため、このようなコードが危険であることは承知しています。ただし、それはこの質問の範囲ではありません。

4

3 に答える 3

4

アドレスを返すことと参照を返すことを混同しています:

int& returnpointer() { ... }

ここでreturnpointer()は、 への参照を返しますint。参照は、特定のタイプのオブジェクトのエイリアスです。参照はポインターとは異なるセマンティクスを持っているため、異なる目的を果たす傾向があります。

非常に重要ないくつかの違いは、参照をデフォルトで構築できない (構築するものが何もない) ことと、それらをリセットできないことです。それらは既存のオブジェクトを参照するように初期化する必要があり、存続期間中は同じオブジェクトを参照します。

一方、ポインターは値 (アドレスを表す) を保持し、これらの値は有効期間中に変更できます。ポインターは、別のオブジェクトを指すようにするnullptrか、または完全にランダムな場所を指すようにすることができます (逆参照すると、未定義の動作につながる可能性があります)。

両方の例が間違っていることに注意してください。最初の例は、関数に対してローカルな変数へのポインターを返します。2 つ目は、今度は参照を使用して同じことを行います。

于 2013-03-13T15:21:46.343 に答える
0

int&アドレス取得演算子ではありません。 int a = 0; int *ptr = &a; それがアドレス取得演算子です。

int& returnpointer() {
    int c = 1;
    int *d = &c;
    return *d;
}

これはアドレスではなく、への参照を返しますint。参照は、別の変数へのエイリアスと考えてください。

int a = 15; int& ref = a;

refは の別の名前になりましaた。

参照とポインターの違いは、参照が NULL になることはなく、常に何かを参照する必要があることです。

ちょっとしたメモ:

int* returnpointer() {
    int c = 1;
    int *d = &c;
    return d;
}

ここでローカル関数変数へのポインターを返していますがc、これは未定義の動作です。関数が終了するとその変数が破棄されるためです。ポインタを返すには、そのようにヒープ上に作成する必要がありますint * f = new int; *f = 5; return f;fこれで、関数の外に戻って使用できるようになりました。

于 2013-03-13T15:24:28.353 に答える
0

C++ では完全に合法であるため、ポインタと参照を返すことができます。

これを考慮してください (私はこれを推奨しません。なぜなら、関数内で割り当てられたメモリを裸の意味で返すことは、所有権の問題のためにほとんど推奨されないからです):

MyObject* create() {
    return new MyObject();
}; // eo create

大丈夫だ。ポインターを返し、オブジェクトを動的に割り当てました。論理的には何も問題はありません (所有権なしでポインターを割り当てて返すことを除いて...ブー!)。それでも、一部の関数はこれを行う必要があります

void* operator new(std::size_t size) {
    return malloc(size);
};

参照 (少し混乱しているようです) も、ポインターが割り当てられたものであっても、完全に実行可能です。インスタンスを管理するマネージャーがあれば、非常に簡単に参照を返すことができます。

class Manager {
private:
    std::list<MyClass*> objects_;

public:
    Manager() {
    };
    ~Manager() {
        for(auto& o : objects_) {
            delete o;
        };
    };

    Myclass& create() {
        o = new MyClass();
        objects_.push_back(o);
        return *o;
    };
};

マネージャーがオブジェクトの有効期間を管理するため、上記はまったく問題ありません。

于 2013-03-13T15:26:55.167 に答える