提问者:小点点

推导std::Vector::Back()的返回类型


我知道标题有点模棱两可,但我想知道,如果我们要为一些STL容器(即vector或list)制作一个包装类,返回一些返回元素引用的方法的正确方式是什么。 请考虑以下代码:

template<typename T>
class wrapper{

private:
std:vector<T> v;

public:
T back() const {
return v.back();
}

};

根据我的理解,back()方法将返回对vector中最后一个对象的constlvalue引用,那么如果我们通过副本返回它会发生什么,我们将获得引用的副本还是对象的副本? 这是编译器可以作为返回值优化的一部分来优化的吗?


共3个答案

匿名用户

若要保留引用类型,请使用decltype(auto):

decltype(auto) back() const {
    return v.back();
}

匿名用户

返回一些返回元素引用的方法的正确方式是什么。

正确的方法取决于您的需要,即您需要一个副本还是一个lvalue引用/常量lvalue引用。 我个人建议返回一个常量引用或一个引用。

vector::back()方法将返回对向量中最后一个对象的constlvalue引用

它返回一个reference/const引用。 如果向量常量,则返回常量引用,否则返回引用。 请参阅:std::vector::back

那么,如果我们通过副本返回,会发生什么呢?我们会得到一个引用的副本还是一个对象的副本

只会创建被引用对象的副本。

这是编译器可以作为返回值优化的一部分来优化的吗?

<罢工> 是,从cppreference开始 复制删除:

它取决于类型T,编译器不需要这样做。 从复制选择上的cppreference:

在下列情况下,编译器允许但不是必须省略类对象的复制和移动(自C++11以来)构造,即使复制/移动(自C++11以来)构造函数和析构函数具有可观察到的副作用。 对象被直接构造到存储中,否则它们将被复制/移动到该存储中。 这是一种优化:即使当它发生并且没有调用copy/move(因为C++11)构造函数时,它仍然必须存在并且可以访问(就像根本没有发生优化一样),否则程序的格式不正确:

  • 在对象的初始化中,当源对象是一个无名的临时对象,并且与目标对象具有相同的类类型(忽略cv-限定)时。 当无名临时值是返回语句的操作数时,这种复制省略的变体称为RVO,“返回值优化”。

另外,如果通过复制返回,T的复制构造函数可能会抛出,并且您可能有一个无效的对象。

匿名用户

> 只要向量不是常量,

  • std::vector::back就会返回非常量引用。

    您的方法返回rvalue,因为您将函数定义为返回rvalue,并且只要函数是const,您就无法返回引用

    如果要将引用作为常量引用返回,请将其标记为常量T&;