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();
}

这当然是一个玩具例子, Foo Bar 结构模仿C++集合的工作。我的问题是,是否有任何好的参数可以使

begin
end
函数对于r值引用(如
bar
)保持可调用状态?或者我应该遵循
foo
中的思想,使代码更安全?据我所知,从临时集合中获取迭代器通常是个坏主意。但另一方面,STL中的所有集合都适用于l值和r值引用,所以我可能遗漏了一些东西


我假设您正在考虑这样一种情况,即对生命周期结束的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中引入右值引用更为古老。因此,即使这是一个完全好的主意,委员会也需要考虑它打破现有代码的成本。