有沒有什麼辦法可以查看默認函數(例如,默認拷貝構造函數,默認賦值運算符),如VC++ 2008編譯器爲沒有定義它們的類生成的?查看編譯器生成的默認函數?
回答
使用clang
編譯器,您可以通過傳遞-ast-dump
參數來查看它們。鏘仍處於發展階段,但你已經可以使用它的這些東西:
[[email protected] cpp]$ cat main1.cpp
struct A { };
[[email protected] 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();
};
[[email protected] cpp]$
我希望這是你問什麼。讓我們改變代碼並再次查看。
[[email protected] cpp]$ cat main1.cpp
struct M { M(M&); };
struct A { M m; };
[[email protected] 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();
};
[[email protected] cpp]$
通知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
[[email protected] 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
}
現在,我不明白,中間語言(這是在llvm.org定義)。但是您可以使用llvm編譯器將所有代碼翻譯爲C:
[[email protected] 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;
}
Tada!注意它是如何在複製構造函數和默認構造函數中設置虛擬表指針的。希望這可以幫助。
可以在Windows 7上運行Clang?我找不到MS窗口的任何下載。 – Southsouth 2012-01-14 15:52:23
爲什麼「結構A」是以下生成的代碼的一部分 struct A { public: struct A; inline A(); ... }
–
Southsouth
2012-01-14 16:02:46
您可以使用調試器跟蹤代碼以查看發生了什麼。例如:
#include <string>
struct A {
int a[100];
char c;
std::string s;
};
int main() {
A a;
A b(a);
}
在複製構造函數的構造'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)
最後是拷貝構造函數調用。如果你想了解更多的細節,你也可以追蹤到。但是,如果你的問題是「我怎麼能看到複製構造函數等的C++代碼」,答案是你不能,因爲沒有任何 - 編譯器生成彙編器或機器代碼(取決於在你的編譯器上),而不是C++代碼。
您確定您需要查看此功能嗎?
默認情況下,編譯器通過調用每個成員變量上的複製構造函數或賦值運算符來創建它們。
問題是,當您使用使用引用計數來管理數據的對象時,默認的複製構造函數將創建對象的副本,但不會創建對象指向的數據的副本。這也是指針的情況。所以如果你有類:
class aClass
{
int one;
int *ptwo;
};
默認的複製構造函數只複製的數據a和指針b。但是他不復制b指向的數據。如果你,如果你想這個類,而不是複製指針ptwo的價值使用這個類像
aClass a, b;
a.ptwo = new int;
a.one = 1;
*(a.ptwo) = 2;
b = a;
*(b.ptwo) = 1;
//a.ptwo now points to an integer with the value of 1
,你需要自己的拷貝賦值運算符的功能。如果你對更多的細節感興趣,那麼默認函數的作用是什麼以及什麼不是,那麼你可以看一下書「Effective C++」。
它有關於這個東西的整章,它解釋了什麼類的默認功能做什麼,不做什麼,他們應該做什麼,什麼時候寫你自己的。如果你只是想知道這個功能,我相信你可以在網上獲得一個數字版本。
編譯器生成的方法是抽象的,它們在源代碼中不存在。
看看下面的例子,我試着解釋一下編譯器生成的方法應該在源代碼級別執行什麼樣的四個。從這裏你應該能夠推斷任何普通班級。
如果你有一個這樣的類:
class X: public Base
{
int* a;
double b;
Y c;
};
那麼編譯器會生成以下等效:
X::X() // Default constructor
:Base() Calls the base class default constructor
//,a pointers are POD no default initialization
//,b double are POD no default initialization
,c() //Call default constructor on each non POD member
{}
X::~X() // Default destructor
{}
// Destructor for each non POD member in reverse order
~c() calls the destructor of the class type
//~b double are POD no destructor
//~a pointers are POD no destructor
~Base() // Calls the base class destructor
X::X(X const& copy)
:Base(copy) // calls the base class copy constructor
// Copies each member using its copy constructor
,a(copy.a) // Pointers copied (Note just the pointer is copied, not what it points at)
,b(copy.b) // Double copied.
,c(copy.c) // Uses copy constructor of the class type (must be accessible)
{}
X& X::operator=(X const& copy)
{
Base::operator=(copy); // Calls the base class assignment operator
// Copies each member using the members assignment operator
a = copy.a; // Pointers copied (Note just the pointer is copied, not what it points at)
b = copy.b; // Double copied
c = copy.c; // Uses assignment operator of the class type (must be accessible)
return *this;
}
另請參閱:http://stackoverflow.com/a/1810320/14065 – 2012-10-12 17:49:01
- 1. 編譯器生成的默認構造函數的工作 - C++
- 2. 當編譯器會生成默認的構造函數派生類
- 3. C++編譯器如何合成默認拷貝構造函數
- 4. 默認的Python編譯器
- 5. 默認目錄查看器的默認編碼
- 6. cmake和默認編譯器
- 7. 即使使用用戶定義的構造函數,編譯器何時仍會生成默認構造函數?
- 8. 由IBM的企業COBOL編譯器生成的查看代碼
- 9. 如何查看編譯器爲OpenMP構造生成的代碼
- 10. 如何查看VC++編譯器生成的.cod文件?
- 11. VB/C#:查看編譯器命令行生成的IDE
- 12. 編譯器何時不創建默認構造函數?
- 13. 是構造函數生成的默認構造函數嗎?
- 14. 默認的虛擬析構函數是否阻止編譯器生成的移動操作?
- 15. 在編譯時生成函數
- 16. 設置默認的編譯器
- 17. 設置默認的Java編譯器
- 18. 默認的maven編譯器設置
- 19. Rcpp和默認的C++編譯器
- 20. GTEST失敗,默認的編譯器
- 21. 如何定義默認的快速查看器查看器
- 22. LINQ to Entites 4.0查詢默認編譯?
- 23. 編譯器執行並提供默認構造函數的構造函數代碼中會發生什麼?
- 24. 默認模板的哪個編譯器參數在函數中參數
- 25. 是否可以查看由JVM熱點編譯器生成的機器代碼?
- 26. 繼承和編譯器生成的函數
- 27. 爲什麼編譯器生成的模板函數
- 28. VS2010是否支持'控制編譯器生成的函數'?
- 29. 使用默認參數調用函數時發生編譯錯誤
- 30. 編譯和使用非默認編譯器Qt的問題
似乎有關於你的問題有些混亂。你是說如何查看函數原型,如何查看哪些是默認的以及我已經實現了哪些,或者如何查看默認實現的代碼? – 2010-01-24 23:45:10