理解C++运算符重载
Understanding C++ operator overloading
我今天阅读了一个哈希竞赛的来源,发现了这个:
#define BYTES_IN_BLOCK 1024
struct block{
uint8_t v[BYTES_IN_BLOCK];
block(){ memset(v, 0, BYTES_IN_BLOCK); }
uint64_t& operator[](uint8_t i){ return *(uint64_t*)(v + 8 * i); }
};
然后,在代码的稍后,有这样的:
state = new block[cost]; // cost is a uint32_t (like 1024)
// Probably 50 lines of code.
block prev_block;
prev_block = state[foo]; // foo is a uint32_t
我搞不清楚这是在干什么。现在,我懂C了,但C++不太懂。请耐心等我一下。
这部分:return *(uint64_t*)(v+8*i)
应该返回一个uint64_t
,并且在我测试它时会这样做:
state->v[8*10] = 12;
uint64_t bar = *(uint64_t*)(v+8*10);
printf("%" PRIu64 "n", bar);
所以这一切都是有道理的。
但是这个:
prev_block = state[foo];
毫无意义。既然state
是block*
,那么prev_block
现在应该"是"state
,对吗?但事实并非如此,因为它们的数组不同。
state->v[8*12] = 12;
printf("%" PRIu64 "n", (*state)[12]);
prev_block = state[12];
printf("%" PRIu64 "n", (*(&prev_block))[12]);
那么,这里到底发生了什么?
您混淆了此处涉及的两个operator[]
。在上一个示例中,您设置了state[0][12] = 12
,并将其与state[12][12]
进行比较。由于state
是block*
,所以state[n]
只是正常的阵列访问;它不调用CCD_ 15中定义的CCD_。
state = new block[cost];
prev_block = state[foo];
类似于:
int* arr = new int[size];
int a = arr[index];
这是基本的C++。我不知道为什么这会令人困惑。
这里有许多概念混淆。我要把我看到的所有问题都说一遍,因为它们都很重要,而不仅仅是直接的答案。
state
是指向块的指针,但state[0]
应该只是一个块,特别是状态中的第一个块,也是*state
的结果。
prev_block = state[foo];
块中的所有数据都很简单,只是一个自包含的字节数组,因此它应该可以直接复制,而无需任何特殊帮助。prev_block = state[foo]
应将状态[foo]复制到prev_block。由于它是一个副本,地址会有所不同。
在提供的打印输出代码中:
state->v[8*12] = 12;
为了清晰起见,将其分解。CCD_ 20将访问状态数组的第一个元素。state->v[8*12]
将访问状态[0]的v[8*12]。CCD_ 22将状态[0]的v[8*12]设置为12。这意味着v的字节96将是12。要引用不同的状态,可以使用(state + array_index)->v[8*12];
或state[array_index].v[8*12];
。我发现后者更可读。
printf("%" PRIu64 "n", (*state)[12]);
(*state)
为您提供阵列中的第一个状态,也就是state[0]
。(*state)[12]
使用state[0]
的[]运算符,定义为uint64_t& operator[](uint8_t i){ return *(uint64_t*)(v + 8 * i); }
这将返回一个64位int,从状态[0].v[12*8]的地址开始,由数组v的下8个字节组成(v[96]到v[103],得到12,0,0,0,00,0,0,0,0(。这将是12,或者是一个巨大的数字,这取决于系统的endian。包装printf将打印返回的数字。
prev_block = state[12];
将状态数组的第13个元素复制到prev_block,假设state = new block[cost];
创建了足够的块。没有什么神奇的,但除了零之外不应该有任何东西,因为唯一设置了任何值的状态是state[0]。您要么想在此处复制state[0]
,要么向上写几行state[12]
。
printf("%" PRIu64 "n", (*(&prev_block))[12]);
*和&在完成任何事情之前互相抵消。然后,它将打印出如上所述使用block[]运算符的结果。应该为零。
- 为什么Mat类的两个对象可以在不重载运算符+的情况下添加
- 重载运算符new[]的行为取决于析构函数
- 为什么将值返回函数传递给重载=运算符对运算符函数有效,而对其他运算符无效
- 在 myVector 类中重载运算符 + 时出错
- 为什么常量词在重载运算符中不与 ostream 对象一起使用<<?
- 如何在 cpp 中重载运算符 +=?
- C++ 如何重载 [] 运算符并进行函数调用
- 重载运算符的范围是什么?它是否会影响作为类成员的集合的插入函数?
- 为什么我可以在不重载 "=" 运算符的情况下将一个对象分配给另一个对象?
- 重载运算符有地址吗?
- 如何迭代重载运算符 [] 的类?
- 重载运算符与添加问题
- 模板基类中的重载运算符
- 如何调用用于重载运算符"<<"的 friend 函数?
- 在 C++17 中的命名空间和子命名空间中重载运算符是不明确的
- 重载运算符<<采用谷歌 C++ 风格
- C++ 如何正确重载 + 运算符
- cout (<<) 重载运算符不打印减去的矩阵
- 如何在 c++ 中重载运算符 + 以便能够 whrite c_str = "smth" + c_str;
- 重载运算符*以获取对另一个类的实例的引用