[英]Understanding C++ operator overloading
I was reading the source of a hashing competition today, and came across this: 我今天正在阅读哈希竞赛的源代码,并且发现:
#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); }
};
Then, a little later in the code, there's this: 然后,在代码的后面,有以下内容:
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
What I can't figure out is what this is doing. 我不知道这是在做什么。 Now, I understand C, but C++ not so much. 现在,我了解C,但是对C ++的了解不多。 Bear with me here for a second. 在这里忍受我一秒钟。
This part: return *(uint64_t*)(v+8*i)
should return a uint64_t
, and does so when I tested it: 这部分: 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);
So that all makes sense. 这样就很有意义了。
But this: 但是这个:
prev_block = state[foo];
Makes no sense. 没有意义。 Since state
is block*
, prev_block
should now "be" state
, correct? 由于state
为block*
,因此prev_block
现在应为“ state
,对吗? But it doesn't, because their arrays are different. 但这不是因为它们的数组不同。
state->v[8*12] = 12;
printf("%" PRIu64 "\n", (*state)[12]);
prev_block = state[12];
printf("%" PRIu64 "\n", (*(&prev_block))[12]);
So, what exactly is going on here? 那么,这到底是怎么回事?
state = new block[cost];
prev_block = state[foo];
is analogous to: 类似于:
int* arr = new int[size];
int a = arr[index];
That's basic C++. 那是基本的C ++。 I am not sure why that is confusing. 我不确定为什么会造成混淆。
You are mixing up the two operator[]
s involved here. 您正在混淆此处涉及的两个operator[]
。 In your last example, you set state[0][12] = 12
, and you're comparing it to state[12][12]
. 在上一个示例中,您设置了state[0][12] = 12
,并将其与state[12][12]
。 Since state
is a block*
, state[n]
is just normal array access; 由于state
是一个block*
,所以state[n]
只是普通的数组访问; it doesn't invoke the operator[]
defined in block
. 它不会调用block
定义的operator[]
。
There is confusion with a number of concepts here. 这里有很多概念的困惑。 I'm going to blast through all the ones I see because they are all important, not just the immediate answer. 我将介绍所有看到的内容,因为它们都很重要,而不仅仅是即时答案。
state
is a pointer to block, but state[0]
should just be a block, specifically the first block in state and also the result of *state
. state
是一个指向块的指针,但是state[0]
应该只是一个块,特别是state中的第一个块以及*state
的结果。
prev_block = state[foo];
All of the data in block is simple, just a self-contained array of bytes, so it should be directly copy-able without any special assistance. 块中的所有数据都很简单,只是一个独立的字节数组,因此它应该可以直接复制,而无需任何特殊帮助。 prev_block = state[foo]
should copy state[foo] to prev_block. prev_block = state[foo]
应该将state [foo]复制到prev_block。 Since it's a copy, the addressing will be different. 由于是副本,因此寻址将有所不同。
In the printout code provided: 在提供的打印输出代码中:
state->v[8*12] = 12;
Breaking his down for clarity. 为清晰起见,将他分解。 state->
is going to access the first element of the state array. state->
将访问状态数组的第一个元素。 state->v[8*12]
is going to access v[8*12] of state[0]. state->v[8*12]
将访问状态[0]的v [8 * 12]。 state->v[8*12] = 12;
is going to set v[8*12] of state[0]to 12. This means byte 96 of v is going to be 12. To reference a different state you can use (state + array_index)->v[8*12];
将状态[0]的v [8 * 12]设置为12。这意味着v的字节96将为12。要引用其他状态,可以使用(state + array_index)->v[8*12];
or state[array_index].v[8*12];
或state[array_index].v[8*12];
I find the latter more readable. 我发现后者更具可读性。
printf("%" PRIu64 "\n", (*state)[12]);
(*state)
gives you the first state in the array, AKA state[0]
. (*state)
给出数组中的第一个状态,即AKA state[0]
。 (*state)[12]
uses state[0]
's [] operator, defined as uint64_t& operator[](uint8_t i){ return *(uint64_t*)(v + 8 * i); }
(*state)[12]
使用state[0]
的[]运算符,定义为uint64_t& operator[](uint8_t i){ return *(uint64_t*)(v + 8 * i); }
uint64_t& operator[](uint8_t i){ return *(uint64_t*)(v + 8 * i); }
This is going to return a 64 bit int starting at the address of state[0].v[12*8] and comprised of the next 8 bytes of array v (v[96] through v[103], resulting in 12,0,0,0,0,0,0,0). 这将返回一个64位int,该int从状态[0] .v [12 * 8]的地址开始,由数组v(v [96]至v [103]的后8个字节)组成,结果为12 0,0,0,0,0,0,0)。 This will be 12 or a god-awful big number depending on the system's endian . 根据系统的字节序,这将是12或一个令人敬畏的大数字。 The wrapping printf is going to print the returned number. 包装的printf将打印返回的数字。
prev_block = state[12];
Is going to copy the 13th element of the state array to prev_block, assuming enough blocks were created by state = new block[cost];
假设state = new block[cost];
创建了足够的块,则将状态数组的第13个元素复制到prev_block state = new block[cost];
. 。 Nothing magical, but there shouldn't be anything there but zeros because the only state that has any values set is state[0]. 没什么了不起的,但是除了零之外,什么也没有,因为唯一设置了任何值的状态是state [0]。 You either wanted to copy state[0]
here or write to state[12]
up a few lines. 您要么想在这里复制state[0]
,要么要写几行到state[12]
。
printf("%" PRIu64 "\n", (*(&prev_block))[12]);
the * and & cancel each other out before accomplishing anything. *和&在完成任何操作之前会互相抵消。 It will then print out the result of using the block [] operator as above. 然后它将打印出使用如上所述的block []运算符的结果。 Should be zero. 应该为零。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.