「あれvectorの中身がみんな同じになっちゃったんですけど」
STL(Standard Template Library)のstd::vetctorを使いはじめた状況で生じがちなシーンだ。
C/C++のはまりどころ
文字列を渡している気になっているのは、文字列の先頭アドレスを渡しているにすぎない。char name[20]で静的に確保された領域の場所は、同じままなので、同一のアドレスがそのつど渡されている。
そのため、for文でそのつど値を設定したつもりが、最後にその領域に書き込まれた値だけが表示される結果になっている。
std::string 型を使って、以下のように書けば、目的の動作をする(2015/11/18 修正)。
bug_vector.cpp
# include <iostream>
# include <string>
# include <vector>
# include <stdio.h>
int main(int argc, char* argv[]){
std::vector<int> nums;
for (int i = 0; i < 5; i++){
nums.push_back(i);
}
for (int i = 0; i < 5; i++){
std::cout << nums[i] << std::endl;
}
std::vector<char*> names;
for (int i = 0; i < 5; i++){
char name[20];
sprintf(name, "file%04d.txt", i);
names.push_back(name);//渡しているのは文字列の入っているメモリの先頭アドレス。
}
for (int i = 0; i < 5; i++){
std::cout << names[i] << std::endl;//受け取ったアドレスにある文字を終末記号まで表示。
}
std::vector<std::string> fnames;
for (int i = 0; i < 5; i++){
fnames.push_back("file" + std::to_string(i) + ".txt");
}
for (int i = 0; i < 5; i++){
std::cout << fnames[i] << std::endl;
}
exit(0);
}
実行結果.txt
0
1
2
3
4
file0004.txt
file0004.txt
file0004.txt
file0004.txt
file0004.txt
file0.txt
file1.txt
file2.txt
file3.txt
file4.txt
問題の残るらしいコード(2015/11/17時点の初出コードから抜粋。)
このコードを書いたときには、fnameという変数で作ったオブジェクトが、fnameというローカル変数が書き換えられても
vetctorの中に残っているものだと思い込んでいる。
言語仕様・STLの仕様からみてどうなのかを、このコードを書いた人は理解していない。
bug_vector2.cpp
# include <iostream>
# include <string>
# include <vector>
# include <stdio.h>
int main(int argc, char* argv[]){
std::vector<std::string> fnames;
for (int i = 0; i < 5; i++){
std::string fname = "file" + std::to_string(i) + ".txt";
fnames.push_back(fname);
}
for (int i = 0; i < 5; i++){
std::cout << fnames[i] << std::endl;
}
exit(0);
}