Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/142.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ []算子的正确模拟_C++_Operators - Fatal编程技术网

C++ []算子的正确模拟

C++ []算子的正确模拟,c++,operators,C++,Operators,考虑数字类包含数字数组的情况。我希望类用户能够轻松地访问数字,因此我重载了[]运算符,这样用户就可以按十的幂选择一个数字,例如,数字[2]是表示数百的数字,依此类推。该类是索引安全的-如果用户指定索引超出范围,则返回0(10=0010) 然而,设置一个数字需要更多的努力,因为如果指数超过容纳数字的内部表的大小,则必须扩展后者 很明显,必须选择不同的方法,无论用户是否想要检索数字,以及何时想要存储数字。我提出了以下解决方案(这些类是局部的,只是为了说明这个想法): Digit类中的运算符显然调用了

考虑数字类包含数字数组的情况。我希望类用户能够轻松地访问数字,因此我重载了[]运算符,这样用户就可以按十的幂选择一个数字,例如,数字[2]是表示数百的数字,依此类推。该类是索引安全的-如果用户指定索引超出范围,则返回0(10=0010)

然而,设置一个数字需要更多的努力,因为如果指数超过容纳数字的内部表的大小,则必须扩展后者

很明显,必须选择不同的方法,无论用户是否想要检索数字,以及何时想要存储数字。我提出了以下解决方案(这些类是局部的,只是为了说明这个想法):

Digit类中的运算符显然调用了一些私有数字的方法,这样用户就可以分配一个值并检索一个值。我也可以采取不同的行动,无论用户是否想要检索值,以及何时想要存储值

然而,const有一个问题。如果Number类实例为const,则除非将运算符[]标记为const,否则无法调用它。但是,无法实例化Digit类,因为它需要Number&,而传递const Number&

一种解决方案涉及到使用const_cast,但感觉就像使用了hack——更不用说,删除const将允许用户使用Digit的操作符=,修改number实例。与使用const_cast或编写另一个类(例如ConstDigit)不同,有没有解决此问题的方法


另一个问题:我不希望用户存储Digit的实例,因为它只是为了方便用户而提供的。私有副本构造函数防止用户存储数字,如:

auto digit = number[5];
但是,他仍然可以通过引用存储数字:

auto digit & = number[5];
通过引用将数字传递给digit(请参阅digit构造函数),以防止指针出现问题,但在这种情况下不会阻止AV:

auto number = new Number();
auto & digit = (*number)[5];
delete number;
digit = 12;
我可能会禁止用户在号码上使用新的运算符,但可能还有其他方法


一个较长的答案,为什么我不能通过引用返回数字

这个数字被保存为两个独立的向量,一个表示整数部分,一个表示分数部分(我已经简化了这个例子,但在这里它并不重要)。比如说,

123.456
存储为

intPart : {3, 2, 1}
fracPart : {4, 5, 6}
如果用户请求第100位的数字,我只需检查它是否超出数组边界并返回0(因为-正如我所提到的,10=0010=00010=…等等)

但是,如果用户希望设置数字,我必须扩展数组以填充所有剩余的指数,例如

100 // user wants to set millions' digit to 5
5 [000] 100 // i have to add these empty digits
当然,我也可以在[]操作符中这样做。但是,如果用户决定将第100位设置为0,我将不得不免费添加98位,如果他尝试这样做,我甚至无法进行检查(并且数字应该存储在最小可能的表示形式中,既不存在前导零,也不存在尾随零)。在他完成任务后,我也没有办法压缩仓库


当然,解决方案之一是删除[]操作符并使用getter/setter。但关键是要使类易于使用,[]运算符比一对getter/setter方法更能满足这一假设:)

我将从第二个问题开始回答:如果您获取引用,则必须确保它在您想要访问它时仍然有效。在你的例子中,情况绝对不是这样。我认为这应该是一个简化的示例,以显示引用的对象在通过先前存储的引用访问之前被销毁的情况。你不能(直接)解决这个问题

您也可以在STL中偶然发现这个“问题”。例如,如果对向量元素进行引用,然后在向量中插入某些内容,请注意,由于新的内存分配,容器内容可能已移动到其他位置,因此引用(可能)无效


我认为避免这种情况的唯一方法是使用智能指针。至少要保证对对象的访问是安全的。如果某些代码更改了您背后的数字,而将
(*number)[5]
替换为新的数字,您将无法访问新对象

现在来回答第一个问题:目前,我看不出您打算如何在
数字
对象上设置某个数字。您确实有一个数字赋值运算符,但由于
Number::operator[]
按值返回数字,因此无法使用它设置数字

我假设我的(错误)理解仅仅是由于一个不完整的代码示例。请适当延长。现在,我假设
数字
数字
数字
的构造函数中初始化,并且您的
操作符[]
仅用于访问

一般来说,您可以创建一个
const
版本的所述运算符,该运算符返回
const Digit
。如果您不能100%确定对象不是常量,请不要使用
const\u cast
删除
const
。否则,您将获得未定义的行为。但是,使用
const_cast
向非常量对象添加/删除
const
是安全的。这对于为
const
和非
const
访问方法重用代码非常有用。非
const
方法可以添加
const
,调用
const
访问方法,然后从返回值中安全地删除
const
(这取决于您的实现)。有关更多详细信息,请参阅Scott Meyers的“高效C++”

也就是说,我必须补充一点,在调用
操作符[]
时,我通常希望引用一个对象,这可能允许我更改对象(例如:
std::vector
std::map
)。如果仅用于只读访问,则按常量引用或常量值返回,而不是按(非常量)值返回。否则,先生
100 // user wants to set millions' digit to 5
5 [000] 100 // i have to add these empty digits
Number[5] = 12;