C++ 不应该';t begin()和end()只能为类的l值引用调用吗?
考虑以下代码:C++ 不应该';t begin()和end()只能为类的l值引用调用吗?,c++,c++11,C++,C++11,考虑以下代码: struct iterator{}; struct foo { iterator begin() &{ return {}; } iterator end() &{ return {}; } }; struct bar { iterator begin(){ return {}; } iterator end(
struct iterator{};
struct foo {
iterator begin() &{
return {};
}
iterator end() &{
return {};
}
};
struct bar {
iterator begin(){
return {};
}
iterator end(){
return {};
}
};
void baz(){
//this obviously wouldn't compile
//vvvvvvvvvvvvv
//foo().begin();
bar().begin();
}
这当然是一个玩具例子,
和begin
函数对于r值引用(如end
)保持可调用状态?或者我应该遵循bar
中的思想,使代码更安全?据我所知,从临时集合中获取迭代器通常是个坏主意。但另一方面,STL中的所有集合都适用于l值和r值引用,所以我可能遗漏了一些东西foo
我假设您正在考虑这样一种情况,即对生命周期结束的prvalue调用
begin
,因此导致foo()。begin()
成为一个悬空指针,因为临时foo()
已被销毁
但情况并非总是如此。仅仅因为一个值是prvalue或xvalue,并不意味着从调用foo::begin()
和iterator::operator*
时,foo
对象将被销毁或清空。考虑这一点:
#include <utility>
template<class T> void do_something_with(const T&);
template<class T>
void baz(T&& it) {
auto begin = std::forward<T>(it).begin();
auto end = std::forward<T>(it).end();
for (; begin != end; ++begin) {
do_something_with(*begin);
}
}
void bar() {
baz(foo());
// Calls `baz<foo>(foo())`, with `decltype(it)` being `foo&&`
}
#包括
模板void do_something_with(const T&);
模板
void baz(T&it){
auto begin=std::forward(it).begin();
auto end=std::forward(it).end();
for(;begin!=end;++begin){
用(*开始)做某事;
}
}
空条(){
baz(foo());
//调用'baz(foo())`,其中'decltype(it)`是'foo'&&`
}
但这是一个完全有效的用例。不要将值类型(右值或左值)与生存期混淆。请注意,许多begin()
和end()
成员函数都比C++11中引入右值引用更为古老。因此,即使这是一个完全好的主意,委员会也需要考虑它打破现有代码的成本。