有没有办法查看由编译器(如VC++ 2008)为未定义它们的类生成的默认函数(例如,默认复制构造函数,默认赋值运算符)?
Joh*_*itb 11
使用clang编译器,您可以通过传递-ast-dump参数来查看它们.Clang仍处于开发阶段,但您已经可以将它用于以下事情:
[js@HOST2 cpp]$ cat main1.cpp
struct A { };
[js@HOST2 cpp]$ clang++ -cc1 -ast-dump main1.cpp
typedef char *__builtin_va_list;
struct A {
public:
struct A;
inline A();
inline A(struct A const &);
inline struct A &operator=(struct A const &);
inline void ~A();
};
[js@HOST2 cpp]$
Run Code Online (Sandbox Code Playgroud)
我希望这就是你所要求的.让我们改变代码再看一遍.
[js@HOST2 cpp]$ cat main1.cpp
struct M { M(M&); };
struct A { M m; };
[js@HOST2 cpp]$ clang++ -cc1 -ast-dump main1.cpp
typedef char *__builtin_va_list;
struct M {
public:
struct M;
M(struct M &);
inline struct M &operator=(struct M const &);
inline void ~M();
};
struct A {
public:
struct A;
struct M m;
inline A();
inline A(struct A &);
inline struct A &operator=(struct A const &);
inline void ~A();
};
[js@HOST2 cpp]$
Run Code Online (Sandbox Code Playgroud)
注意A现在隐式声明的复制构造函数如何具有非const引用参数,因为它的一个成员也具有(成员m),并且M没有声明默认构造函数.
要获取生成的代码,您可以让它发出虚拟机中间语言.让我们看一下生成的代码:
struct A { virtual void f(); int a; };
A f() { A a; a = A(); return a; } // using def-ctor, assignment and copy-ctor
[js@HOST2 cpp]$ clang++ -cc1 -O1 -emit-llvm -o - main1.cpp | c++filt
[ snippet ]
define linkonce_odr void @A::A()(%struct.A* nocapture %this) nounwind align 2 {
entry:
%0 = getelementptr inbounds %struct.A* %this, i32 0, i32 0 ; <i8***> [#uses=1]
store i8** getelementptr inbounds ([3 x i8*]* @vtable for A, i32 0, i32 2), i8*** %0
ret void
}
define linkonce_odr %struct.A* @A::operator=(A const&)(%struct.A* %this,
%struct.A* nocapture) nounwind align 2 {
entry:
%tmp = getelementptr inbounds %struct.A* %this, i32 0, i32 1 ; <i32*> [#uses=1]
%tmp2 = getelementptr inbounds %struct.A* %0, i32 0, i32 1 ; <i32*> [#uses=1]
%tmp3 = load i32* %tmp2 ; <i32> [#uses=1]
store i32 %tmp3, i32* %tmp
ret %struct.A* %this
}
define linkonce_odr void @A::A(A const&)(%struct.A* nocapture %this, %struct.A* nocapture)
nounwind align 2 {
entry:
%tmp = getelementptr inbounds %struct.A* %this, i32 0, i32 1 ; <i32*> [#uses=1]
%tmp2 = getelementptr inbounds %struct.A* %0, i32 0, i32 1 ; <i32*> [#uses=1]
%tmp3 = load i32* %tmp2 ; <i32> [#uses=1]
store i32 %tmp3, i32* %tmp
%1 = getelementptr inbounds %struct.A* %this, i32 0, i32 0 ; <i8***> [#uses=1]
store i8** getelementptr inbounds ([3 x i8*]* @vtable for A, i32 0, i32 2), i8*** %1
ret void
}
Run Code Online (Sandbox Code Playgroud)
现在,我不明白这种中间语言(在llvm.org中定义).但是您可以使用llvm编译器将所有代码转换为C:
[js@HOST2 cpp]$ clang++ -cc1 -O1 -emit-llvm -o - main1.cpp | llc -march=c -o - | c++filt
[snippet]
void A::A()(struct l_struct.A *llvm_cbe_this) {
*((&llvm_cbe_this->field0)) = ((&_ZTV1A.array[((signed int )2u)]));
return;
}
struct l_struct.A *A::operator=(A const&)(struct l_struct.A *llvm_cbe_this, struct l_struct.A
*llvm_cbe_tmp__1) {
unsigned int llvm_cbe_tmp3;
llvm_cbe_tmp3 = *((&llvm_cbe_tmp__1->field1));
*((&llvm_cbe_this->field1)) = llvm_cbe_tmp3;
return llvm_cbe_this;
}
void A::A(A const&)(struct l_struct.A *llvm_cbe_this, struct l_struct.A *llvm_cbe_tmp__2) {
unsigned int llvm_cbe_tmp3;
llvm_cbe_tmp3 = *((&llvm_cbe_tmp__2->field1));
*((&llvm_cbe_this->field1)) = llvm_cbe_tmp3;
*((&llvm_cbe_this->field0)) = ((&_ZTV1A.array[((signed int )2u)]));
return;
}
Run Code Online (Sandbox Code Playgroud)
田田!注意它如何在复制构造函数和默认构造函数中设置虚拟表指针.希望这可以帮助.
小智 7
您可以使用调试器跟踪代码以查看正在进行的操作.例如:
#include <string>
struct A {
int a[100];
char c;
std::string s;
};
int main() {
A a;
A b(a);
}
Run Code Online (Sandbox Code Playgroud)
在复制构造函数的'b'构造处设置断点.VC++ 6调试器中此时的汇编器输出是:
12: A b(a);
00401195 lea eax,[ebp-1B0h]
0040119B push eax
0040119C lea ecx,[ebp-354h]
004011A2 call @ILT+140(A::A) (00401091)
Run Code Online (Sandbox Code Playgroud)
最后一个是复制构造函数调用.如果您想了解更多细节,也可以追溯到这一点.
但是,如果您的问题是"如何查看复制构造函数的C++代码等",答案是您不能,因为没有 - 编译器生成汇编程序或机器代码(取决于您的编译器)对他们而言,不是C++代码.
| 归档时间: |
|
| 查看次数: |
1861 次 |
| 最近记录: |