C++ 如何为const对象重载[],以便赋值不会导致编译错误
我需要为非常量和常量对象重载[]运算符。对于非常量对象,应该可以读取和分配值。对于常量对象,应该可以读取值,但值赋值不应影响元素。同时,代码应该是可编译的 我创建的声明:C++ 如何为const对象重载[],以便赋值不会导致编译错误,c++,operator-overloading,C++,Operator Overloading,我需要为非常量和常量对象重载[]运算符。对于非常量对象,应该可以读取和分配值。对于常量对象,应该可以读取值,但值赋值不应影响元素。同时,代码应该是可编译的 我创建的声明: int &operator[](int element_index); const int &operator[](int element_index) const; 此类声明的问题在于,以下代码: const MyObject some_object(); some_object[1] = 100; 导
int &operator[](int element_index);
const int &operator[](int element_index) const;
此类声明的问题在于,以下代码:
const MyObject some_object();
some_object[1] = 100;
导致编译错误:“分配只读位置”(存在某些_对象[1]并且可以读取)。所需的行为是不会出现编译错误。我试图找到一种方法来返回元素的副本,但不幸的是,我没有找到一种有效的组合。这是一件很难办的事情,因为它会导致无法维护的客户端代码,而分配不会产生任何影响,但可以进行编排。您需要从non-
const
索引运算符返回一些可以分配给的内容,而不会影响容器。下面,const
索引运算符按值返回DummyInt
,其中的赋值是一个const
函数(因此您可以在返回的临时变量上调用它,而无需将其存储到命名变量),该函数不做任何操作。它还从容器中捕获整数值,并提供一个操作符int()const
函数来访问它
可在以下位置编辑/运行:
不清楚:
some_object[1]=100的效果如何代码>在运行时的状态(如果没有编译错误)?请注意,修改声明为const
的对象是未定义的行为。为什么不希望出现编译器错误?修改一个const对象违背了最不令人惊讶的规则。还要注意恼人的解析:const MyObject some_object()代码>是一个意外的函数声明,而不是一个变量定义。这闻起来像一个。为什么你认为你需要允许某个对象[1]=100代码>当它没有达到预期效果时?更糟糕的是,一些非常量对象[1]=100代码>看起来一样,但做了一些完全不同的事情。对不起,我不相信。你不应该为了让单元测试正常工作而破坏那些工作得如此糟糕的东西。我宁愿说你需要修改测试。尝试分配给常量的测试只有在分配失败的情况下才会成功……为什么不简单地让操作符[](int n)const
通过复制返回int
?这不会有同样的效果吗?@MooingDuck:如果它按值返回一个int
的副本,你不能在没有编译器错误的情况下分配给它。犹豫是否向上投票,因为它是正确的,但任何人都不应该编写这样的代码:P@user463035818:我能理解!我犹豫着回答,但“不要这样做”有点无聊,从技术上讲,知道如何做到这一点也有点意思。
#include <iostream>
struct C
{
struct DummyInt
{
int n_;
operator int() const { return n_; }
const DummyInt& operator=(int) const { return *this; }
};
DummyInt operator[](int n) const { return DummyInt{a_[n]}; }
int& operator[](int n) { return a_[n]; }
int a_[3];
};
int main()
{
const C c{ 4, 5, 6 };
c[1] = 2;
for (auto x : c.a_) std::cout << x << '\n';
C c2{ 7, 8, 9 };
c2[1] = 2;
for (auto x : c2.a_) std::cout << x << '\n';
}
4
5
6
7
2
9