【发布时间】:2014-12-05 11:32:57
【问题描述】:
按预期工作的示例
#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() 时分配,但它是对这个迭代器的引用。所以,这个警告不应该出现,因为我没有分配内存。但是由于我不知道这种机制是如何工作的,所以我想学习它以编写一致的代码。看来我可以忽略这个警告,不是吗?
【问题讨论】:
-
你从哪里得知
begin()返回一个引用? -
您在the description of
std::vector::begin()的哪个位置看到任何提及参考结果的内容?它返回一个对象。 -
@Werner:您想知道为什么未定义的行为不会给出明确定义的行为?因为它是未定义的。 (在这种情况下,它可能只是意味着被破坏对象的存储在被复制到局部变量之前没有被重用,所以它仍然包含旧值。但你不能依赖这种行为。)跨度>
-
@Werner:确实,在对象的生命周期结束后使用对象总是 UB,返回对自动变量或临时变量的引用总是错误的。一旦程序的生命周期结束,就没有(便携式)方法可以阻止程序重用其内存。您需要按值返回迭代器。
-
仅供参考,您的实际调用代码是有效的,因为您从不调用您的
begin()和end()成员MyClass。相反,您直接调用myClass.myvec.begin()和myClass.myvec.end()。您的 Ub 蓬勃发展的成员未被召唤。
标签: c++ vector reference iterator