Ask questions
The following code, can compile the chain has been connected?
void f(constint &value){}class Test{public: staticconstint1;};int main(){ f(Test::a); return0;}
My first feeling is: there should be no problem, right. In the VS 2013 experiment, the smooth passage, all normal. However, GCC is an error: Undefined reference to ' test::a ' why is this?
Analyze problems
The environment for writing this article is the GCC 4.8.2 (Ubuntu 14.04, X86 platform). Note that the discussion in this article is only for static const members of the class, which is known as Class scope. The circumstances of namespace scope are not within our scope of discussion.
Save the above code as test.cpp and then compile it with GCC:
g++ -c -o test.o test.cpp
After this command is executed, we will get the TEST.O file in the directory. Next, we use objdump to view the symbol table:
objdump -x test.o
We can see output similar to the following:
SYMBOL TABLE:00000000L DF *abs*00000000Test. cpp00000000L D. Text 00000000 . Text00000000L D. Data 00000000 . Data00000000L D. BSS 00000000 . BSS00000000L D. Note. GNU-stack00000000 . Note. GNU-stack00000000L D. Eh_frame00000000 . Eh_frame00000000L D. Comment 00000000 . Comment00000000G F. Text 00000005_z1frki00000005G F. Text 00000019Main00000000*und*00000000_zn4test1ae
In the last line above, _zn4test1ae is the test::a that corresponds to the declaration in our program. The reason why this is so complicated and strange is that the compiler did the mangling processing.
Did you notice the UND ? According to the explanation of the document:
UND : If the section was referenced in the file being dumped and not defined there
That is, _zn4test1ae is referenced in this. o file, but it has a definition of wood. Therefore, the newspaper undefined reference to ' test::a ' of the fault, it is also understandable.
So, does our program really refer to _zn4test1ae? Well, let's keep looking down.
Enter the following command:
g++-Stest.cpp
We can get the assembly code like this (done a collation, excerpt):
main: pushl %ebp movl %esp%ebp subl $4%esp movl $_ZN4Test1aE, (%esp) ;看到没?_ZN4Test1aE ! call _Z1fRKi ;调用函数f movl $0%eax leave ret
Although we have analyzed why the error, however, we have a question, that is, why the following code is OK?
void f(constintvalue//这里没有 &{}class Test{public: staticconstint1;};int main(){ f(Test::a);//没问题 return0;}
Well, with the foundation of the front, I believe the reader gentlemen already know how to analyze. We can use the same method to look at its assembly code:
main: pushl %ebp movl %esp%ebp subl $4%esp movl $1, (%esp) ;看到没?1,不是_ZN4Test1aE,也不是Test::a call _Z1fi movl $0%eax leave ret
That is, in this case, the compiler simply takes test::a as a placeholder, where the actual use is replaced by 1.
Solve the problem
Know the reason, then how to solve it? Well, at least three ways:
1. We can define (rather than declare) test::a. Yes, the static const int a = 1 above, not its definition. If you want to define, then we should do this:
void f(constint &value)//还是传引用{}class Test{public: staticconstint a;};constint1;//定义aint main(){ f(Test::a);//现在没问题了 return0;}
Interested readers can look at this program corresponding to the symbol table, you will find Test::a is placed in the program's Rodata section, rather than UND .
2. If you just declare a, then we can use it in the same way as the value, that's fine. That is to use only its value, not to get its address (and, of course, to include references.) References are also addresses in nature).
3. Use the enumeration type. Yes, enumerate! Like this:
void f(constint &value)//还是传引用{}class Test{public: enum1//枚举,而不是 static const};int main(){ f(Test::a);//没问题 return0;}
So, how does the compiler handle this situation? Just leave the reader gentlemen as an exercise.
For more discussion and exchange on the cornerstone and practice of program design, please follow this blog and Sina Weibo songzi_tea
static const in C + +