知らないauto指定子について行ってはいけない
std::vector<std::uint32t> 長いですね。
Perlの国の民にはこのような長い形名をタイプするのは苦行以外の何物でもありません。
そこで苦しむPerl民のために、C++11から型推論により長い形名のタイプから我々を開放してくれるauto指定子が導入されました。
しかしこのauto指定子はさながら、純真な女児を甘いお菓子で誘惑する知らないおじさんのようなものなのです。
純真なのでオブジェクトの参照を返すところでauto指定子を使いたいとします。
以下のソースコードをご覧ください。
#include <vector> #include <iostream> #include <cstdint> class A { private: std::vector<std::uint32_t> v; public: A(){ for(int i = 0; i < 10; ++i){ v.push_back(i * 2); } } int get(int i){ return v[i]; } std::vector<std::uint32_t>& ref(){ return v; } }; int main(){ A obj; std::cout << obj.get(3) << std::endl; auto r = obj.ref(); r[3] = 1; std::cout << obj.get(3) << std::endl; }
これをコンパイルし、実行すると恐ろしいことにこうなります。
6 6
怖いですね。知らないと3時間ぐらいは無駄にしそうですね。
ここでは普通の値渡しと同じようにコピーが行われています。
正しくは呼ぶ側のautoを
auto& r = obj.ref();
と明示的に参照の形で宣言してやる必要があります。
(実行結果)
6 1
このautoの特性はポインタに対しても同様です。
これは純真な女児を陥れる大きな罠であり、物心ついた子どもには必ず教える必要があると思います。