我知道标题有点模棱两可,但我想知道,如果我们要为一些STL容器(即vector或list)制作一个包装类,返回一些返回元素引用的方法的正确方式是什么。 请考虑以下代码:
template<typename T>
class wrapper{
private:
std:vector<T> v;
public:
T back() const {
return v.back();
}
};
根据我的理解,back()
方法将返回对vector
中最后一个对象的constlvalue引用,那么如果我们通过副本返回它会发生什么,我们将获得引用的副本还是对象的副本? 这是编译器可以作为返回值优化的一部分来优化的吗?
若要保留引用类型,请使用decltype(auto)
:
decltype(auto) back() const {
return v.back();
}
返回一些返回元素引用的方法的正确方式是什么。
正确的方法取决于您的需要,即您需要一个副本还是一个lvalue引用/常量lvalue引用。 我个人建议返回一个常量引用或一个引用。
vector::back()
方法将返回对向量中最后一个对象的constlvalue引用
它返回一个reference/const引用。 如果向量
是常量
,则返回常量引用,否则返回引用。 请参阅:std::vector
那么,如果我们通过副本返回,会发生什么呢?我们会得到一个引用的副本还是一个对象的副本
只会创建被引用对象的副本。
这是编译器可以作为返回值优化的一部分来优化的吗?
<罢工> 是,从cppreference开始 复制删除:
它取决于类型T
,编译器不需要这样做。 从复制选择上的cppreference:
在下列情况下,编译器允许但不是必须省略类对象的复制和移动(自C++11以来)构造,即使复制/移动(自C++11以来)构造函数和析构函数具有可观察到的副作用。 对象被直接构造到存储中,否则它们将被复制/移动到该存储中。 这是一种优化:即使当它发生并且没有调用copy/move(因为C++11)构造函数时,它仍然必须存在并且可以访问(就像根本没有发生优化一样),否则程序的格式不正确:
另外,如果通过复制返回,T
的复制构造函数可能会抛出,并且您可能有一个无效的对象。
> 只要向量不是常量,
std::vector
就会返回非常量引用。
您的方法返回rvalue
,因为您将函数定义为返回rvalue
,并且只要函数是const
,您就无法返回引用
。
如果要将引用作为常量
引用返回,请将其标记为常量T&;