[解決済み] 未使用のメンバ変数はメモリを食うか?
質問
メンバ変数を初期化し、それ以上参照/使用しない場合、実行時に RAM を消費しますか?
struct Foo {
int var1;
int var2;
Foo() { var1 = 5; std::cout << var1; }
};
上記の例では、メンバー 'var1' は値を取得し、コンソールに表示されます。しかし、'Var2' は全く使用されない。したがって、実行時にそれをメモリに書き込むことは資源の無駄遣いになります。コンパイラはこのような状況を考慮して、未使用の変数を無視するのでしょうか?
どのように解決するのですか?
C++の黄金律である "as-if"。 1 には次のように書かれています。 であれば 観測可能な動作 が未使用のデータメンバーの存在に依存しない場合、コンパイラはそれを最適化して取り除くことができます。 .
未使用のメンバ変数はメモリを消費しますか?
いいえ("本当に"未使用である場合)。
さて、ここで2つの疑問が浮かびます。
- 観測可能な動作がメンバーの存在に依存しないのはどんな場合か?
- 実際のプログラムではそのような状況は発生するのでしょうか?
まずは例から。
例
#include <iostream>
struct Foo1
{ int var1 = 5; Foo1() { std::cout << var1; } };
struct Foo2
{ int var1 = 5; int var2; Foo2() { std::cout << var1; } };
void f1() { (void) Foo1{}; }
void f2() { (void) Foo2{}; }
もし gcc にこの翻訳ユニットをコンパイルするよう とすると、出力されます。
f1():
mov esi, 5
mov edi, OFFSET FLAT:_ZSt4cout
jmp std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
f2():
jmp f1()
f2
と同じです。
f1
と同じで、実際の
Foo2::var2
. (
Clang は似たようなことをします
).
ディスカッション
これは2つの理由で違うという人もいるかもしれません。
- これはあまりにも些細な例です。
- 構造体は完全に最適化されているため、カウントされません。
さて、良いプログラムとは、複雑なものを単純に並べるのではなく、単純なものを賢く複雑に組み立てるものです。実際の生活では、コンパイラが最適化するよりも、単純な構造を使って大量の単純な関数を書きます。たとえば
bool insert(std::set<int>& set, int value)
{
return set.insert(value).second;
}
これは正真正銘、データ・メンバー(ここでは。
std::pair<std::set<int>::iterator, bool>::first
)が使われていない本物の例です。何だと思いますか?
それは最適化されて離れている
(
ダミーセットによる単純な例
を使うこともできます)。
今こそ Max Langhofの素晴らしい回答を読む を読むのに最適なタイミングでしょう (私のためにアップヴォートしてください)。最終的に、なぜ構造の概念が、コンパイラーが出力するアセンブリ レベルで意味をなさないのかを説明しています。
"しかし、X を行うと、未使用のメンバーが最適化されてしまうというのは問題です!"
この回答は間違っているに違いないと主張するコメントが多数寄せられています。
assert(sizeof(Foo2) == 2*sizeof(int))
のような)何らかの操作が何かを壊してしまうからです。
Xがプログラムの観察可能な動作の一部である場合 2 である場合、コンパイラは最適化することができません。プログラム上で観察可能な効果を持つであろう "unused"データメンバーを含むオブジェクトに対する多くの操作があります。もしそのような操作が行われた場合、またはコンパイラが何も行われていないことを証明できない場合、その "unused" データメンバーはプログラムの観察可能な動作の一部となります。 であり、最適化されることはありません。 .
観察可能な動作に影響を与える操作には、これらに限定されませんが、以下のものがあります。
-
オブジェクトのタイプのサイズを取る (
sizeof(Foo)
), - 未使用のデータメンバの後に宣言されたデータメンバのアドレスを取得します。
-
のような関数でオブジェクトをコピーする。
memcpy
, -
オブジェクトの表現を操作する(例えば
memcmp
), - としてオブジェクトを修飾する 揮発性 ,
- その他 .
1)
この文書における意味記述は,パラメタ化された非決定論的抽象機械を定義する。この文書は,適合する実装の構造に対して,何の要件も課さない。特に、抽象機械の構造をコピーしたり、エミュレートしたりする必要はない。むしろ、適合する実装は、以下に説明するように、抽象機械の観察可能な動作をエミュレートすること(のみ)が要求される。
2) アサートのパスやフェイルがそうであるように
関連
-
[解決済み] error: 'ostream' does not name a type.
-
[解決済み】C++の変数はイニシャライザーを持っているが、不完全な型?
-
[解決済み] Javaでメモリーリークを発生させるにはどうしたらいいですか?
-
[解決済み] explicit キーワードの意味は?
-
[解決済み] C++11では、標準化されたメモリモデルが導入されました。その意味するところは?そして、C++プログラミングにどのような影響を与えるのでしょうか?
-
[解決済み] 0.1fを0にすると、なぜ10倍もパフォーマンスが落ちるのですか?
-
[解決済み] アプリケーションやプロセスの実際のメモリ使用量を測定するにはどうすればよいですか?
-
[解決済み] 構造体のsizeofは、なぜ各メンバーのsizeofの合計と等しくないのですか?
-
[解決済み】ローカル変数のメモリはスコープ外からアクセスできる?
-
[解決済み】C++のコンパイルにはなぜそんなに時間がかかるのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】coutはstdのメンバではない
-
[解決済み】C++ - 解放されるポインタが割り当てられていないエラー
-
[解決済み】C++でユーザー入力を待つ【重複あり
-
[解決済み] [Solved] Error C1083: Cannot open include file: 'stdafx.h'
-
[解決済み】C++でランダムな2倍数を生成する
-
[解決済み】デバッグアサーションに失敗しました。C++のベクトル添え字が範囲外
-
[解決済み】fpermissiveフラグは何をするのですか?
-
[解決済み】「std::operator」で「operator<<」にマッチするものがない。
-
[解決済み] 警告:暗黙の定数変換でのオーバーフロー
-
[解決済み] 変数サイズのオブジェクトが初期化されないことがある c++