void maybeModify(int& x); // may modify x in some way
void hurtTheCompilersOptimizer(short size, int array[]){// This function is designed to do something particularly troublesome// for optimizers. It will constantly call maybeModify on array[0] while// adding array[1] to array[2]..array[size-1]. There's no real reason to// do this, other than to demonstrate the power of references.for (int i = 2; i < (int)size; i++) {maybeModify(array[0]);array[i] += array[1];}}
优化编译器可能会意识到我们正在访问一堆[0]和[1]。它会喜欢优化算法以:
void hurtTheCompilersOptimizer(short size, int array[]){// Do the same thing as above, but instead of accessing array[1]// all the time, access it once and store the result in a register,// which is much faster to do arithmetic with.register int a0 = a[0];register int a1 = a[1]; // access a[1] oncefor (int i = 2; i < (int)size; i++) {maybeModify(a0); // Give maybeModify a reference to a registerarray[i] += a1; // Use the saved register value over and over}a[0] = a0; // Store the modified a[0] back into the array}
void maybeModify(int* x); // May modify x in some way
void hurtTheCompilersOptimizer(short size, int array[]){// Same operation, only now with pointers, making the// optimization trickier.for (int i = 2; i < (int)size; i++) {maybeModify(&(array[0]));array[i] += array[1];}}
>>> The address that locates a variable within memory iswhat we call a reference to that variable. (5th paragraph at page 63)
>>> The variable that stores the reference to anothervariable is what we call a pointer. (3rd paragraph at page 64)
只要记住这一点,
>>> reference stands for memory location>>> pointer is a reference container (Maybe because we will use it forseveral times, it is better to remember that reference.)
更重要的是,我们几乎可以参考任何指针教程,指针是指针算术支持的对象,它使指针类似于数组。
看下面的陈述,
int Tom(0);int & alias_Tom = Tom;
alias_Tom可以理解为alias of a variable(与typedef不同,alias of a type)Tom。忘记这种语句的术语是创建Tom的引用也是可以的。
#include <iostream>int main(int argc, char** argv) {// Create a string on the heapstd::string *str_ptr = new std::string("THIS IS A STRING");// Dereference the string on the heap, and assign it to the referencestd::string &str_ref = *str_ptr;// Not even a compiler warning! At least with gcc// Now lets try to print it's value!std::cout << str_ref << std::endl;// It works! Now lets print and compare actual memory addressesstd::cout << str_ptr << " : " << &str_ref << std::endl;// Exactly the same, now remember to free the memory on the heapdelete str_ptr;}
int main(int argc, char** argv) {// In the actual new declaration let immediately de-reference and assign it to the referencestd::string &str_ref = *(new std::string("THIS IS A STRING"));// Once again, it works! (at least in gcc)std::cout << str_ref;// Once again it prints fine, however we have no pointer to the heap allocation, right? So how do we free the space we just ignorantly created?delete &str_ref;/*And, it works, because we are taking the memory address that the reference isstoring, and deleting it, which is all a pointer is doing, just we have to specifythe address with '&' whereas a pointer does that implicitly, this is sort of likecalling delete &(*str_ptr); (which also compiles and runs fine).*/}
Int a = 6, b = 5;Int& rf = a;
Cout << rf << endl; // The result we will get is 6, because rf is referencing to the value of a.
rf = b;cout << a << endl; // The result will be 5 because the value of b now will be stored into the address of a so the former value of a will be erased
Std ::vector<int>v(10); // Initialize a vector with 10 elementsV[5] = 5; // Writing the value 5 into the 6 element of our vector, so if the returned type of operator [] was a pointer and not a reference we should write this *v[5]=5, by making a reference we overwrite the element by using the assignment "="
// receives an alias of an int, an address of an int and an int valuepublic void my_function(int& a,int* b,int c){int d = 1; // declares an integer named dint &e = d; // declares that e is an alias of d// using either d or e will yield the same result as d and e name the same objectint *f = e; // invalid, you are trying to place an object in an address// imagine writting your name in an address fieldint *g = f; // writes an address to an addressg = &d; // &d means get me the address of the object named d you could also// use &e as it is an alias of d and write it on g, which is an address so it's ok}
x++;z++;
*y++; // what people assume is happening behind the scenes, but isn't. it would produce the same results in this example.*(y++); // this one adds to the pointer, and then dereferences it. It makes sense that a pointer datatype (an address) can be incremented. Just like an int can be incremented.
引用是一个常量指针。int * const a = &b与int& a = b相同。这就是为什么没有常量引用这样的东西,因为它已经是常量了,而对常量的引用是const int * const a。当你使用-O0编译时,编译器将在这两种情况下将b的地址放在堆栈上,作为类的成员,它也将出现在堆栈/堆上的对象中,与你声明了常量指针相同。使用-OFast,可以自由优化它。常量指针和引用都被优化了。
#include <iostream>int b=1;struct A {int* i=&b; int& j=b;};A a;int main() {std::cout << &a.j << &a.i;}
The address of b is stored twice in the object.
a:.quad b.quad b