3

私がこれまでに読んだことから、参照変数はまったくメモリを必要としないようです。代わりに、参照しているのとまったく同じ変数として扱われますが、別の名前が付けられています。

ただし、次のコードを実行すると、常にそうであるとは限りません。

#include <cstdio>
struct A
{
    int m[3];
};
struct B: A
{
    B():x(m[0]), y(m[1]), z(m[2]){}
    int& x;
    int& y;
    int& z;
};
int main(){
    printf("%u, %u\n", sizeof(A), sizeof(B));
    return 0;
}

出力:

12, 40

なぜBはAよりもずっと大きいのですか?

たとえば、Bx で Bm[0] にアクセスできる他の方法はありますか?

4

3 に答える 3

7

私がこれまでに読んだことから、参照変数はまったくメモリを必要としないようです。

さらに読む必要があります ;) 真剣に、参照は魔法ではありません。したがって、現実の世界では、参照がどのオブジェクトにバインドされているかに関する情報をオブジェクトが保存する必要があります。したがって、概念的には参照にサイズはありませんが、実際にはポインターと非常によく似ており、通常、コンパイラーはポインターのみを使用します。ポインターの動作とは異なる動作 (null ではない、再割り当て可能でない、逆参照する必要がない) は、コンパイル時にコンパイラによって強制されます。

したがって、基本的には、A のサイズにパディングを加えたサイズと 3 つのポインターのサイズが表示されます。私はあなたsizeof(int)が 4 とsizeof(void*)8 である 64 ビット システムにいると思います:

 12 bytes for the A subobject (4 for each int)
+ 4 bytes padding (to get to a multiple of 8 bytes)
+24 bytes for the 3 references/pointers in B (8 for each one)
--------------
 40 bytes total

b他の質問については、 typeのオブジェクトが与えられた場合、 public inおよび public に継承されているため、直接Bアクセスできます。発生した参照オーバーヘッドなしで別の名前を付けることはできません。b.m[0]A

于 2013-04-17T14:07:46.270 に答える
4

あなたは物事を間違って解釈しています。純粋にローカルで使用される参照は、オプティマイザによって削除される可能性があり、多くの場合削除されます。存続期間中は、まだどこかに (レジスターのように) 保管する必要があることに注意してください。

コンパイラは、ローカル変数ほど簡単にオブジェクトの寿命を予測できないため、メンバー参照を実際に置き換えて破棄することはできません。実際のコンテンツへのポインター (4 バイトまたは 8 バイト) を保持する必要があります。オブジェクトの存続期間中、メンバーの一貫性を保ちます。

于 2013-04-17T14:06:13.480 に答える
2

参照は、null にすることはできず、「再配置」することはできません (最初に指していたもの以外のものを指すようにする) ポインターのようなものです。したがって、参照はポインターと同じ量のスペースを必要とするかもしれません (ただし、これは保証されていません)。したがって、3 つの int、アライメント用の 4 バイト、3 つの 8 バイト ポインターは 40 バイトになり、例は完全に合理的になります。

B.x()より多くのスペースを占有することなく、値を返すようなメソッドを作成できます。しかし、C++ には「プロパティ」がないためB.x、スペースを必要としないものを返すことはできません (つまり、メンバー変数アクセスのように見えても、メソッド呼び出しのように振る舞うものを作成することはできません)。

于 2013-04-17T14:05:20.990 に答える