为什么不对运算符[]重载的左值和右值? [英] Why isn't operator[] overloaded for lvalues and rvalues?

查看:642
本文介绍了为什么不对运算符[]重载的左值和右值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

标准C ++容器只为向量< T> 容器提供了 operator [] code> deque< T> 。它返回一个 T& (除了向量< bool> ,我将忽略)是一个左值。这意味着在这样的代码中,

 向量< BigObject> makeVector(); // factory function 

auto copyOfObject = makeVector()[0]; // copy BigObject

copyOfObject 建。假设 makeVector()返回一个右值向量,期望 copyOfObject 要移动构造。



如果 operator [] rvalue容器的 operator [] 可以返回一个右值引用,即右值:

 模板< typename T> 
container {
public:
T& operator [](int index)& ;; // for lvalue objects
T&&& operator [](int index)&& ;; // for rvalue objects
...
};

在这种情况下, copyOfObject



有这样的重载是一个坏主意的原因吗?有没有理由为什么在C ++ 14中没有为标准容器做?

解决方案

p>

这种方法没有什么内在的错误;类成员访问遵循类似的规则( E1.E2 是xvalue,如果 E1 是右值, E2 命名一个非静态数据成员,而不是一个引用,参见[expr.ref] /4.2),容器中的元素在逻辑上类似于非静态数据成员。 p>

对于 std :: vector 或其他标准容器的一个重大问题是,它可能会破坏一些旧代码。考虑:

  void foo(int&); 
std :: vector< int>酒吧();

foo(bar()[0]);

最后一行将停止编译 operator [] 对一个右值向量返回一个xvalue。或者 - 并且可以更糟 - 如果有一个 foo(const int&)重载,它将默认开始调用该函数。



另外,在容器中返回一堆元素并且只使用一个元素已经相当低效。可以说,这样做的代码可能不关心速度,所以小的性能改进不值得引入潜在的突破性变化。


The standard C++ containers offer only one version of operator[] for containers like vector<T> and deque<T>. It returns a T& (other than for vector<bool>, which I'm going to ignore), which is an lvalue. That means that in code like this,

vector<BigObject> makeVector();       // factory function

auto copyOfObject = makeVector()[0];  // copy BigObject

copyOfObject will be copy constructed. Given that makeVector() returns an rvalue vector, it seems reasonable to expect copyOfObject to be move constructed.

If operator[] for such containers was overloaded for rvalue and lvalue objects, then operator[] for rvalue containers could return an rvalue reference, i.e., an rvalue:

template<typename T>
container {
public:
    T& operator[](int index) &;       // for lvalue objects
    T&& operator[](int index) &&;     // for rvalue objects
...
};

In that case, copyOfObject would be move constructed.

Is there a reason this kind of overloading would be a bad idea in general? Is there a reason why it's not done for the standard containers in C++14?

解决方案

Converting comment into answer:

There's nothing inherently wrong with this approach; class member access follows a similar rule (E1.E2 is an xvalue if E1 is an rvalue and E2 names a non-static data member and is not a reference, see [expr.ref]/4.2), and elements inside a container are logically similar to non-static data members.

A significant problem with doing it for std::vector or other standard containers is that it will likely break some legacy code. Consider:

void foo(int &);
std::vector<int> bar();

foo(bar()[0]);

That last line will stop compiling if operator[] on an rvalue vector returned an xvalue. Alternatively - and arguably worse - if there is a foo(const int &) overload, it will silently start calling that function instead.

Also, returning a bunch of elements in a container and only using one element is already rather inefficient. It's arguable that code that does this probably doesn't care much about speed anyway, and so the small performance improvement is not worth introducing a potentially breaking change.

这篇关于为什么不对运算符[]重载的左值和右值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆