#include <iostream>
#include <vector>
struct MyClass{
const std::vector<float>::iterator& begin(){
return myvec.begin();
}
const std::vector<float>::iterator& end(){
return myvec.end();
}
std::vector<float> myvec;
};
int main(){
std::vector<float> mainvec(8,0);
MyClass myClass;
myClass.myvec = mainvec;
for (std::vector<float>::iterator it = myClass.begin();
it != myClass.end();++it){
std::cout << *it << " " ;
}
std::cout << std::endl;
}
このコードでは、次の出力が得られます。
0 0 0 0 0 0 0 0
#include <iostream>
#include <vector>
struct MyClass{
const std::vector<float>::iterator& begin(){
return myvec.begin();
}
const std::vector<float>::iterator& end(){
return myvec.end();
}
std::vector<float> myvec;
};
int main(){
std::vector<float> mainvec(8,0);
MyClass myClass;
myClass.myvec = mainvec;
const std::vector<float>::iterator& end_reference = myClass.end();
for (std::vector<float>::iterator it = myClass.begin();
it != end_reference;++it){
std::cout << *it << " " ;
}
std::cout << std::endl;
}
このコードでは、次の出力が得られます。
"empty output"
それは私が起動する問題(誤って)ベクター有するbegin()
とend()
代わりMyClassの方法のを。
私の疑問を表すために、次の最小限のコードがあります。
#include <iostream>
#include <vector>
struct MyClass{
const std::vector<float>::iterator& begin(){
return myvec.begin();
}
const std::vector<float>::iterator& end(){
return myvec.end();
}
std::vector<float> myvec;
};
int main(){
std::vector<float> mainvec(8,0);
MyClass myClass;
myClass.myvec = mainvec;
for (std::vector<float>::iterator it = myClass.myvec.begin();
it != myClass.myvec.end();++it){
std::cout << *it << " " ;
}
std::cout << std::endl;
}
8行目と12行目に次の警告が表示されます。
returning reference to local temporary object [-Wreturn-stack-address] [cpp/gcc]
しかし、プログラムをコンパイルして実行すると、次のようになります。
0 0 0 0 0 0 0 0
したがって、ローカル参照は、を返すときに破棄されないようですmyvec.begin()
。私が最初にコードを書いたとき、それが問題になるとは思っていませんでした。私の頭の中では、ベクトルからのbegin()メソッドが最初のベクトルの場所へのイテレータ参照を返すので、このイテレータはそうではありません。 myvec.begin()を実行するときに割り当てられますが、このイテレータへの参照です。したがって、メモリを割り当てていないため、この警告は表示されないはずです。しかし、このメカニズムがどのように機能するかわからないので、一貫性のあるコードを書くためにそれを学びたいと思います。この警告は無視できるようですよね?
std :: vector :: beginは確かに一時オブジェクトを返します(http://www.cplusplus.com/reference/vector/vector/begin/を参照)
一時オブジェクトをconst参照にバインドし(非const参照では有効ではない)、ローカル変数にすぐにコピーするため、コードは有効ですit
。
編集:私の間違い。これは確かに、一時的なものからconst参照を返すUBでもあります。
ただし、この参照をより長い存続期間を持つ別のconst参照に割り当てると、一時オブジェクトの存続期間が直接割り当てられているconst参照の存続期間まで延長されるため、未定義の動作が発生します。
警告を考慮して、イテレータを返すことをお勧めします。
http://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/も読むことをお勧めします
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加