标准 C++ 容器只提供一个版本的 operator[]
对于像 vector<T>
这样的容器和 deque<T>
.它返回 T&
(除了 vector<bool>
,我将忽略它),这是一个左值。这意味着在这样的代码中,
vector<BigObject> makeVector(); // factory function
auto copyOfObject = makeVector()[0]; // copy BigObject
copyOfObject
将被复制构造。鉴于 makeVector()
返回右值 vector
, 期待 copyOfObject
似乎是合理的移动构建。
如果operator[]
对于此类容器,右值和左值对象重载,然后 operator[]
对于右值容器可以返回一个右值引用,即一个右值:
template<typename T>
container {
public:
T& operator[](int index) &; // for lvalue objects
T&& operator[](int index) &&; // for rvalue objects
...
};
在这种情况下,copyOfObject
将被移动构建。
有没有理由认为这种重载通常不是一个好主意? C++14 中的标准容器没有这样做是有原因的吗?
最佳答案
将评论转化为答案:
这种方法本质上没有错;类成员访问遵循类似的规则(E1.E2
是一个 xvalue,如果 E1
是一个右值并且 E2
命名一个非静态数据成员并且不是引用,参见 [expr.ref]/4.2),容器内的元素在逻辑上类似于非静态数据成员。
为 std::vector
或其他标准容器执行此操作的一个重要问题是它可能会破坏一些遗留代码。考虑:
void foo(int &);
std::vector<int> bar();
foo(bar()[0]);
如果右值 vector 上的 operator[]
返回了一个 xvalue,那么最后一行将停止编译。或者 - 并且可以说更糟 - 如果有 foo(const int &)
重载,它会默默地开始调用该函数。
此外,返回容器中的一堆元素并且只使用一个元素已经相当低效了。有争议的是,执行此操作的代码可能不太关心速度,因此小的性能改进不值得引入潜在的破坏性更改。
关于c++ - 为什么 operator[] 不为左值和右值重载?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51869253/