我在班上有const重载方法:
class A{
public:
typedef int data[10];
data& operator[](int index);
const data& operator[](int index) const;
}
此类正在为其内部数据实现copy-on-write。我认为,由于我允许直接访问数据,因此我必须在每次使用operator[]
时创建共享数据的副本(如果它显然是共享的),而不是operator[] const
。但是,即使代码使用operator []读取数据,但对象本身未声明为const,它仍将导致创建副本,因为将使用operator []。是否有任何语法可以让我选择我正在调用哪些运算符?
答案 0 :(得分:2)
是:const_cast<A const&>(anAObj)[5]
。
答案 1 :(得分:1)
为什么运营商会返回引用单个项目的data&
而不是int&
?
据说你的选择包括:
GetRef
)。const
:static_cast<const A&>(obj)[index]
。答案 2 :(得分:1)
您需要创建一个Proxy类来替换两种方法的返回值。然后,在Proxy类中,您可以适当地处理读取和写入。这里的代码应该编译以演示这个想法(使用无符号整数数组):
typedef unsigned int UINT;
A级{
class Proxy {
public:
Proxy(const UINT &number): _number(number) {}
const Proxy &operator=(const Proxy &obj) {
cout << "Writting...\n";
_number = obj._number;
return *this;
}
operator const UINT &() const {
cout << "Reading...\n";
return _number;
}
private:
UINT _number;
};
公共:
A(UINT *array): _array(array) {}
Proxy operator[](int index) {
return _array[index];
}
const Proxy operator[](int index) const {
return _array[index];
}
私人:
UINT *_array;
};
int main(int argc,char ** argv){
UINT myArray[] = {0, 1, 2, 3, 4};
A a(myArray); // Normal A object
UINT num1 = a[1]; // Reading fine
a[1] = num1; // Writting fine
const A ca(myArray); // Constant A object
UINT num2 = ca[1]; // Reading fine
ca[1] = num2; // Writting NOT fine (compilation error)
return 0;
}
答案 3 :(得分:0)
不,除非你将引用/指针强制转换为常量。或者创建一个常量副本。
A a;
const_cast<const A &> (a)[0] /*.foo ()*/;
答案 4 :(得分:0)
实现data& at(size_t i);
和const data& cat(size_t);
函数,因此您可以在非const对象上调用cat()
来强制执行返回数据的常量。
答案 5 :(得分:0)
如果要实现copy-on-write,则根本不应定义这些订阅运算符。调用对象const
的订阅方法的x
版本的客户端不允许随后使用该引用来修改x
的组件,但该引用仍应反映更改其他客户对x
的(组成部分)做出的贡献。但是,他不会发生写入时复制策略,因为更改将发生在与参考点不同的副本中。
另外两个调用具有相同索引的非const订阅运算符的客户端应该获得(可修改的)对相同 data
对象的引用;但他们不会,因为订阅操作员被调用时会有两个单独的副本。
相反,您可以使用按值返回data
的订阅方法。这避免了为x
组件获取别名的假象(正如我所说,当实现copy-on-write时, }。您还可以提供一个修改x
组件的方法(而不是将此操作拆分为订阅,然后分配给所获得的引用),这可以在内部进行复制,或者仅修改组件这个副本已经制作好的地方。这会使客户端无法使用写时复制实现。
更一般地说,公开返回对内部对象的引用的方法,无论是否const
,都暴露了这些对象存在的实现细节。这限制了以后更改实现的自由度,例如压缩数据或将数据存储在内存以外的地方。