0
#include <iostream>

class Bar
{
    protected:

public:
        int & x;
        Bar(int & new_x)
        :x(new_x)
        {}
        Bar & operator = (const Bar toCopy)
        {
            x = toCopy.x;
            return *this;
        }
};

int main()
{
    int x1(1);
    int x2(2);

    Bar bar = Bar(x1);
    std::cout << bar.x << std::endl;

    bar = Bar(x2);
    std::cout << bar.x << std::endl;

    bar.x = 5;
    std::cout << bar.x << std::endl;

    std::cout << x1 << std::endl;
    std::cout << x2 << std::endl;

}

出力は次のとおりです。

1
2
5
5
2

私がやろうとしているのは、オブジェクト内にコピー xして保存することbarです。

出力は、新しいオブジェクトの値のコピーと取得の両方に関して、代入演算子がその魔法を行っていないことを示唆しています。このリンクをたどりました。

実際のプログラムでは抽象クラスxであるため、参照ではなく値に変更することはできません。x

可能であれば、ヒープ割り当ての使用を控えてください。

EDIT : 1. C++ 言語を解体したばかりであることに気付きました。「C++ian」を話すすべてのコンピューターに謝罪したいと思います。私の動機は、スタックにメンバー抽象変数を割り当てることでした。私が理解している限り、派生クラスのサイズはコンパイル時にわからないため、スタック上では実行できません。2. わかりました... 私は完全に無能です... (いいえ、シャーロック!)。「効果的な C++ プログラミング」@rhalbersma は必読です。必要なものが含まれていますが、どこにもありません(コピー構造、コピー初期化子)..とにかく1か所にあります。

4

3 に答える 3

3

参照は混乱を招く可能性があります。constポインターも同様です。両方について同時に話すことで、物事を明確にしようとします。私は楽観主義者です。

まずはconstポインタ。

というクラスから始めますFoo。このクラスへのポインタを持つことができます -- a Foo*. constこのクラスのインスタンスへのポインタを持つことができます-- a Foo const*. そして、このクラスの非インスタンスconstへのポインタ、つまりa を持つことができます。constFoo*const

Aは、変更できないデータへの変更可能Foo const*なポインタです。

Aは、変更可能Foo*constなデータへの変更できないポインターです。

私はあなたがそれを持っていると仮定します。結局のところ、私は楽観主義者です。次に、参考文献を見てみましょう。

参照がエイリアスであることは事実ですが、物事が他の型に関して具体的な実装を持つ世界でそれらについて考えることが役立つ場合があります。

AFoo&は a に似ていますFoo*const-- you のインスタンスへの変更不可能な「ポインター」Fooは変更できます。つまり、Fooあなたが話しているのは常に同じものですが、その状態を変更できます。

今、それはもう少しです。いくつかの構文糖があります。別の変数への参照を作成すると、&自動的に が実行されます。つまり、 を実行するFoo& f = a;と、これは に似ていFoo*const f = &a;ます。

次に、 を使用すると、ポインターの場合.と同じように動作します。->(そして、(ほとんどの?) 他のオペレーターについても同様です)

第 3 に、代入を行う場合、ポインターの値を変更することはできませんが (変更されているため) const、代わりに、指している対象の値を変更します。に相当Foo& f = a; a = b;するものも同様ですFoo*const f = &a; *f = b;

を使用すると、ポインターではなく、指しているものが割り当てられますoperator=。ただし、トークンoperator=を持っていても、初期化すると は使用されません。=

一般に、初期化は代入と同じではありません。また、初期化と代入で&参照と*ポインターで発生する動作のセマンティクスは大きく異なります。

Foo& f = a; f = b;2 つのまったく異なることを行います。参照の初期化は、「constポインター」部分を初期化します。参照への代入は、指し示すものを変更します。

初期化と代入の両方が指すものを変更する「ポインターセマンティクス」とは対照的に、初期化と代入が参照で異なることをどのように意味するかについての私の個人的な名前は「参照セマンティクス」です。「参照セマンティクス」では、初期化によって指し示されているものが選択され、代入によって指し示されているものの状態が変更されます。

これは非常に紛らわしいので、別の方法で混乱させるのに役立つことを願っています.

于 2013-01-15T15:55:08.437 に答える
3

Bar bar = Bar(x1);割り当てではなく、コピー初期化です。コピー代入演算子ではなく、コピー コンストラクターを呼び出します。

ただし問題は、参照を理解していないことです。メンバーBar::xは別の変数の単なるエイリアスです。それに何かを割り当てると、元のものも変更されます。

于 2013-01-15T15:05:27.797 に答える
0

x内部barは、の「x1」と呼ばれる変数と同じ変数ですmain
これが参照の機能です。参照は変数を受け取り、それを参照するために使用できる別の名前を付けます。
この新しい名前でその変数に対して行うことは、他の名前で行うことと同じです。

まず、後

Bar bar = Bar(x1);

(これはコピーの初期化であり、割り当てではありません)
"bar.x"は、右側の匿名オブジェクト内の "x"と同じ変数を指します。これは、メインの"x1"の別の名前です。

この後、「bar.x」という名前は「x1」という名前と同じ変数を指します。

この線

bar = Bar(x2);

匿名オブジェクトのの値(つまり、2)を割り当てますx。これは、と同じ変数でありx2、内部barでは「x」と呼ばれますが、名前は「x1」ですmain

この線

bar.x = 5;

次に、値5を「bar.x」という名前の変数に割り当てます。この変数も、mainの「x1」と同じ変数です。

別の変数を参照させることはできません。
さまざまな変数を参照できるものが必要な場合は、ポインターを使用する必要があります。

于 2013-01-15T16:08:30.437 に答える