その”static”に意味はあるのか
1 |
static int a = 100; |
static
という単語をつけて変数を宣言すると、関数を抜けても値が保持される。
よくこういう説明を初心者は受けることになる。
実際にそういう説明だった。
1 2 |
static int a; a = 100; |
しかし、偶然にもこのような使い方をしてしまっているのを発見してしまった。
お前、毎回100
を代入してるから意味無いじゃん。
何故こんなことをやってしまったのかさっぱり分からないが、もしかしたら意味があるかもしれないので、考える前に手を動かすことにした。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
#include <iostream> #include <chrono> using namespace std; typedef struct { int a; int b; int c; int d; } example; void func(void) { example ex; ex.a = 100; ex.b = 200; ex.c = 300; ex.d = ex.a + ex.b + ex.c; } int main(void) { const int n = 100000000; auto before = chrono::system_clock::now(); for (int i = 0; i < n; ++i) { func(); } auto after = chrono::system_clock::now(); auto time = chrono::duration_cast<chrono::milliseconds>(after - before); cout << time.count() << "[ms]" << endl; return 0; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
#include <iostream> #include <chrono> using namespace std; typedef struct { int a; int b; int c; int d; } example; void func(void) { static example ex; ex.a = 100; ex.b = 200; ex.c = 300; ex.d = ex.a + ex.b + ex.c; } int main(void) { const int n = 100000000; auto before = chrono::system_clock::now(); for (int i = 0; i < n; ++i) { func(); } auto after = chrono::system_clock::now(); auto time = chrono::duration_cast<chrono::milliseconds>(after - before); cout << time.count() << "[ms]" << endl; return 0; } |
この2つのコードを
1 |
clang++ -std=c++11 -O0 |
でコンパイルして、出力された実行時間を計測した。
static | non-static | |
1 | 338 | 367 |
2 | 346 | 357 |
3 | 335 | 371 |
4 | 332 | 369 |
5 | 349 | 390 |
6 | 359 | 349 |
7 | 354 | 356 |
8 | 315 | 339 |
9 | 353 | 335 |
10 | 353 | 329 |
平均 | 343.4 | 356.2 |
あまり変わらないので、とりあえず何にでもstatic
をつけるのはクソということだ。
まーた間違ったことを学生に教えてるのかけしからんな。
1 |
static char str[] = "あああああ"; //短い文字列ならstaticは不要 |
また、なんかこんなことがプリントに書いてあった。
文字列を変えないのでconst char*
でやれという感じだが、こちらも計測。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
#include <iostream> #include <chrono> using namespace std; typedef struct { int a; int b; int c; int d; } example; void func(void) { char str[] = R"(やあ (´・ω・`) ようこそ、バーボンハウスへ。 このテキーラはサービスだから、まず飲んで落ち着いて欲しい。 うん、「また」なんだ。済まない。 仏の顔もって言うしね、謝って許してもらおうとも思っていない。 でも、このスレタイを見たとき、君は、きっと言葉では言い表せない 「ときめき」みたいなものを感じてくれたと思う。 殺伐とした世の中で、そういう気持ちを忘れないで欲しい そう思って、このスレを立てたんだ。 じゃあ、注文を聞こうか。)"; (void)str; } int main(void) { const int n = 100000000; auto before = chrono::system_clock::now(); for (int i = 0; i < n; ++i) { func(); } auto after = chrono::system_clock::now(); auto time = chrono::duration_cast<chrono::milliseconds>(after - before); cout << time.count() << "[ms]" << endl; return 0; } |
char[] | static char[] | const char* | static const char* | |
1 | 1513 | 270 | 278 | 287 |
2 | 1573 | 286 | 279 | 292 |
3 | 1561 | 274 | 263 | 278 |
4 | 1547 | 268 | 269 | 277 |
5 | 1634 | 279 | 271 | 280 |
6 | 1551 | 269 | 273 | 275 |
7 | 1566 | 263 | 284 | 270 |
8 | 1583 | 265 | 285 | 272 |
9 | 1586 | 263 | 271 | 277 |
10 | 1583 | 258 | 160 | 272 |
平均 | 1569.7 | 269.5 | 263.3 | 278 |
毎回バーボンハウスのコピーが行われるchar[]
は激遅だが、ポインタを使うコードとでは速度は変わらない。
そもそもstatic
つけた時点で、文字列を変えると2回目以降の実行結果に影響する。
文字列の内容を変更しないのであれば、const char*
で文字列リテラルへのポインタを取るのが一般的だし、なぜこんな変なことを学生に教えてるのかやっぱり分からない。