int x = 12;
12
整数リテラルと言われるため、LValueでは使用できません。
- コンパイラはどのようにリテラルにメモリを割り当てますか?
- リテラルの範囲は何ですか?
- スコープに&12が含まれるアドレスを取得できないのはなぜですか?
OK 質問の悪い例。
しかし、質問はまだ有効です:試して
みましょう:
Foo getFoo() {return Foo();}
int func()
{
getFoo().bar(); // Creates temporary.
// before this comment it is also destroyed.
// But it lives for the whole expression above
// So you can call bar() on it.
}
int func2()
{
Foo const& tmp = getFoo(); // Creates temporary.
// Does not die here as it is bound to a const reference.
DO STUFF
} // tmp goes out of scope and temporary object destroyed.
// It lives to here because it is bound to a const reference.
コンパイラは一時オブジェクトにメモリをどのように割り当てますか?
コンパイラまで未定義。
しかし、スタック フレームにもう少し多くのメモリを割り当ててそこに保持するのは非常に簡単です。次に、それを破棄し、スタック フレームのサイズを縮小します (ただし、この回答では、基盤となるハードウェアについて、絶対に実行してはならない多くの想定が行われています (コンパイラが魔法を実行していると考えるのが最善です))。
一時オブジェクトのスコープは何ですか?
;
一時オブジェクトは、const 参照にバインドされていない限り、式 (通常は ) の終わりまで存続します。const 参照にバインドされている場合は、参照が属するスコープの最後まで存続します (いくつかの例外 (コンストラクターなど) を除く)。
スコープに &12 が含まれているアドレスを取得できないのはなぜですか?
質問 12 は一時的なオブジェクトではありません。
整数リテラルです。
あなたの例12
では整数リテラルです。整数リテラルは、ほとんどの場合、即値オペランドとしてマシン命令に「埋め込まれています」。それらはメモリに保存されないため、アドレスを介してアクセスすることも、スコープを持たないこともできません。
int x = 12
のようなものに変換されます
movl 12 address_of_x_or_register
ほとんどすべてのアーキテクチャで。ここでは、12 が命令の一部としてエンコードされています。
明確にするためx
に、メモリ(ローカル変数の場合はスタック、グローバル変数の場合はデータセグメント)に常駐し、最終的に値を含みます12
。RHS「オブジェクト」12は整数リテラルであり、命令の前または実行中にメモリに存在しませんが、命令自体に「存在」します。
1. How does the compiler allocate memory to a temporary object?
string myString = "hello";
この場合、conversion constructor
新しいオブジェクトを初期化するために a が呼び出されます。
2. What is the scope of a temporary object?
一時オブジェクトの寿命はセミコロンまで
3. Why can't we get its address with an &12 in its scope? (in this case "hello")
&12
オブジェクトではなく、変換コンストラクターに渡されるパラメーターです
他の答えはあなたの誤解をほとんどクリアしたので注意してください、しかしこれはそうではありません:
リテラルの範囲は何ですか?
スコープは名前のプロパティ(変数名、関数名、型名、テンプレート名、名前空間名など)であるため、この質問は意味がありません。
リテラルは、名前ではなく、数値の表記です。
オブジェクトは「記憶の中の何か」です。これは、この何かがプロセスのアドレス空間の一部を占有していることを意味します (スタックまたは「空き」メモリのいずれか)。また、必要に応じてアドレスを取得できることも意味します。
一時オブジェクトは単なるオブジェクトです。式を計算するためにそのようなオブジェクトが必要な場合、コンパイラはそれらを作成するためのコードを生成します。
void f(const string&);
void g()
{
f(string("Hello"));
}
f() を呼び出す式により、次のようなコードが生成されます。
これの重要な部分は、式の評価の最後に一時オブジェクトを破棄することです。一時オブジェクトは式自体にのみ存在します (つまり、その場しのぎのスコープです)。次のようなことを試すこともできconst string* ps = &string("Hello")
ますが、コンパイラはおそらくアラームを鳴らします。そのような式は、一時オブジェクトで占有されていたメモリを参照するポインタを作成するためです。文字列オブジェクトのメンバーがまだ含まれているか、プログラム内の次の式によって上書きされる可能性があります (一時オブジェクトを破棄すると、オブジェクトによってヒープに割り当てられたメモリが解放されることは言うまでもありません)。を使用ps
すると、未定義の動作が発生します。
ここで発生するもう 1 つの問題は、 のような式のオブジェクトの性質ですint x = 12
。この場合、xはオブジェクトである場合とそうでない場合があります。これは、コンパイラの設定と、その行に続くコードによって異なります。コンパイラは x をレジスタに配置することを望むかもしれません。このような場合、x はオブジェクトではなく、レジスタにアドレスがないためです (少なくともほとんどのプラットフォームでは)。コンパイラの値を変更しない場合x
、命令で 12 を直接使用することさえ考えられる場合があります。したがって、「12」は命令コードの一部としてのみ存在します。
とにかく、次のコードで何が起こっても、int x = 12
一時12
オブジェクトは作成されません。コンパイラが 12 をメモリに配置する場合、命令は次のようになります (疑似コード):
store immediate address_of_x, 12
レジスタに x が表示された場合は、次のようになります。
move immediate regX, 12
どちらの場合も、12 は (コンパイルされたコード チャンクの) 命令の一部になります。したがって、それは別個のオブジェクトにはなりません。
では、コンパイル中にコンパイラは何をするのでしょうか? 保管所?
これは本当に答えが難しいです。コンパイラは可能な限りコードを最適化します (多くの場合、実行される最適化の量またはレベルはコンパイラ ツールで設定できます)。
与えられた例のように、アセンブリ命令で x を 12 に置き換えることができる場合、x は「最適化され」、x の直接の置換として 12 が使用されます。
「volatile」キーワードを使用すると、コードで使用されるたびに x をチェックするようにコンパイラーをだますことができます。これにより、より大きなプログラムが生成されますが、変数にメモリの場所 (ストレージ) を割り当てるのに役立つ場合があります。