了解C ++运算符重载

时间:2015-07-21 05:09:56

标签: c++ operator-overloading 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];

没有任何意义。由于stateblock*prev_block现在应该“成为”state,对吗?但事实并非如此,因为它们的阵列不同。

state->v[8*12] = 12;
printf("%" PRIu64 "\n", (*state)[12]);
prev_block = state[12];
printf("%" PRIu64 "\n", (*(&prev_block))[12]);

那么,到底发生了什么?

3 个答案:

答案 0 :(得分:1)

state = new block[cost];
prev_block = state[foo];

类似于:

int* arr = new int[size];
int a = arr[index];

这是基本的C ++。我不确定为什么会让人感到困惑。

答案 1 :(得分:1)

你正在混淆这里涉及的两个operator[]。在上一个示例中,您设置了state[0][12] = 12,并将其与state[12][12]进行比较。由于stateblock*state[n]只是正常的数组访问;它没有调用operator[]中定义的block

答案 2 :(得分:1)

这里有许多概念的混淆。我会把所有看到的东西都炸掉,因为它们都很重要,而不仅仅是直接的答案。

state是指向块的指针,但state[0]应该只是一个块,特别是状态中的第一个块,也是*state的结果。

prev_block = state[foo];

块中的所有数据都很简单,只是一个自包含的字节数组,所以它应该可以直接复制而无需任何特殊帮助。 prev_block = state[foo]应该将state [foo]复制到prev_block。由于它是副本,因此寻址方式会有所不同。

在提供的打印输出代码中:

state->v[8*12] = 12;
为了清晰起见,打破了他。 state->将访问state数组的第一个元素。 state->v[8*12]将访问状态[0]的v [8 * 12]。 state->v[8*12] = 12;将把状态[0]的v [8 * 12]设置为12.这意味着v的字节96将是12.要引用不同的状态,您可以使用(state + array_index)->v[8*12];或{ {1}}我发现后者更具可读性。

state[array_index].v[8*12];

printf("%" PRIu64 "\n", (*state)[12]); 为您提供数组中的第一个状态,即AKA (*state)state[0]使用(*state)[12]' s []运算符,定义为state[0]

这将从状态[0] .v [12 * 8]的地址开始返回64位int,并由数组v的后8个字节组成(v [96]到v [103],结果在12,0,0,0,0,0,0,0)。根据系统的endian,这将是12或一个可怕的大数字。包装printf将打印返回的数字。

uint64_t& operator[](uint8_t i){ return *(uint64_t*)(v + 8 * i); }

假设prev_block = state[12]; 创建了足够的块,将状态数组的第13个元素复制到prev_block。没什么神奇的,但是除了零之外不应该有任何东西,因为唯一有任何值设置的状态是state [0]。您要么在此处复制state = new block[cost];,要么向state[0]写几行。

state[12]

*和&在完成任何事情之前取消对方。然后它将打印出如上所述使用block []运算符的结果。应该为零。