目に見える違い
i++ と ++i の速度の比較検証は今回は行わない。
違いを理解していると透明なエラーに3日3晩悩まされる可能性が減ると思われる。
たとえばこんなコードがあるとする。
C
#include <stdio.h>
int main(int argc, char* argv[])
{
int i = 0;
int j = 0;
printf("i++: %d\n", i++);
printf("++j: %d\n", ++j);
return 0;
}
C++
#include <iostream>
int main(int argc, char* argv[])
{
int i = 0;
int j = 0;
std::cout << "i++: " << i++ << std::endl;
std::cout << "++j: " << ++j << std::endl;
return 0;
}
C#
public class Hello
{
public static void Main()
{
int i = 0;
int j = 0;
System.Console.WriteLine("i++: " + i++);
System.Console.WriteLine("++j: " + ++j);
}
}
結果はいくつだろうか?
i++: 0
++j: 1
こうなる。
しかし、こう書くと見かけ上の違いはなくなる。
(以降の説明ではC++のみ)
#include <iostream>
int main(int argc, char* argv[])
{
int i = 0;
int j = 0;
i++;
++j;
std::cout << "i: " << i << std::endl;
std::cout << "j: " << j << std::endl;
if(i == j)
std::cout << "一致";
return 0;
}
i: 1
j: 1
一致
同じだ。
処理速度も最近のコンパイラでは両者最適化が行われ、あまり無い。
ならどちらでも良いのか?
例えばこんなコードはどうだろう。
#include <iostream>
#include <vector>
int main(int argc, char* argv[])
{
std::vector<int> v = { 11, 22, 33, 44, 55 };
int i = -1;
while (i++ < std::size(v))
std::cout << "index[" << i << "] => " << v.at(i) << std::endl;
return 0;
}
int 型のvectorがあり、要素の数は 5 個、indexは最大 4 。
実際、C++においては範囲forを用いれば良い。(※1)
どちらかというと、C言語で書きうるコードだ。
while (i++ < std::size(v))
とかくと、なにも出力されない。
while (++i < std::size(v))
と書くと
index[0] => 11
index[1] => 22
index[2] => 33
index[3] => 44
index[4] => 55
このように出力される。
先のwhileでは何も出力されなかったが。
が、もし仮に直前で i が 4 になっていたとして次のif文に入るとどうなるのか。
if(i++ < std::size(v))
std::cout << v.at(i) << std::endl;
0x00007FFD257D837A で例外がスローされました (main.exe 内): Microsoft C++ の例外: std::out_of_range
これは領域外アクセスエラーになる。
i++ を使え!
++i を使え!
と言うつもりはない。
気を付けるに越したことはない。
(※1)要素の中身だけが欲しいのなら自分ならこう書くだろう。
for(const auto& e : v)
std::cout << e << std::endl;
11
22
33
44
55
投稿の直前にふと思ったこと。
#include <iostream> #include <vector> int main(int argc, char* argv[]) { std::vector<int> v = { 11, 22, 33, 44, 55 }; int i = -1; while (i++ < std::size(v)) std::cout << "index[" << i << "] => " << v.at(i) << std::endl; return 0; }
while (i++ < std::size(v))
とかくと、なにも出力されない。
何も表示されないのはおかしくないか?
try / catchで捕まえてみる。
#include <iostream>
#include <vector>
int main(int argc, char* argv[])
{
std::vector<int> v = { 11, 22, 33, 44, 55 };
int i = -1;
try
{
while (i++ < std::size(v))
std::cout << "index[" << i << "] => " << v.at(i) << std::endl;
}
catch (const std::out_of_range& e)
{
std::cerr << "Caught std::out_of_range: " << e.what() << std::endl;
}
catch (...)
{
std::cerr << "Unknown Error" << std::endl;
}
return 0;
}
なにも出ない。
whileを2か所に増やしてみる。
try
{
while (i++ < std::size(v))
std::cout << "index[" << i << "] => " << v.at(i) << std::endl;
while (i++ < std::size(v))
std::cout << "index[" << i << "] => " << v.at(i) << std::endl;
}
catch (const std::out_of_range& e)
{
std::cerr << "Caught std::out_of_range: " << e.what() << std::endl;
}
catch (...)
{
std::cerr << "Unknown Error" << std::endl;
}
index[1] => 22
index[2] => 33
index[3] => 44
index[4] => 55
index[5] => Caught std::out_of_range: invalid vector subscript
捕まった。
if(-1 < std::size(v))
if(-1 < v.size())
とやってもtrueが返らなかったので、size()になにかありそうだ。
長くなりそうなのでまた次回。