Có cách nào để xem các hàm mặc định (ví dụ: hàm tạo bản sao mặc định, toán tử gán mặc định) được tạo bởi trình biên dịch như VC++ 2008 cho một lớp không xác định chúng?xem các chức năng mặc định được tạo bởi trình biên dịch?
Trả lời
Với trình biên dịch clang
, bạn có thể xem chúng bằng cách chuyển đối số -ast-dump
. Clang vẫn đang trong giai đoạn phát triển, nhưng bạn đã có thể sử dụng nó cho những việc sau:
[[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]$
Tôi hy vọng đó là những gì bạn yêu cầu. Hãy thay đổi mã và xem lại.
[[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]$
Thông báo như thế nào copy constructor ngầm tuyên bố của A
bây giờ có một số tài liệu tham khảo không const, bởi vì một trong những thành viên của nó có quá (thành viên m
), và rằng M
không có constructor mặc định tuyên bố.
Để nhận mã được tạo, bạn có thể để nó phát ra ngôn ngữ trung gian của máy ảo. Hãy xem mã được tạo cho điều này:
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
}
Bây giờ, tôi không hiểu ngôn ngữ trung gian (được xác định tại llvm.org). Nhưng bạn có thể dịch tất cả mã đó vào C bằng trình biên dịch llvm:
[[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! Chú ý cách nó đặt con trỏ bảng ảo trong hàm tạo bản sao và hàm tạo mặc định. Hi vọng điêu nay co ich.
Clang có thể chạy trên windows 7 không? Tôi không thể tìm thấy bất kỳ tải xuống cho các cửa sổ MS. – Southsouth
Tại sao "struct A;" là một phần của mã được tạo trong các trường hợp sau đây struct A { public: struct A; inline A(); ... }
–
Southsouth
Bạn có thể theo dõi mã bằng trình gỡ rối để xem điều gì đang diễn ra. Ví dụ:
#include <string>
struct A {
int a[100];
char c;
std::string s;
};
int main() {
A a;
A b(a);
}
Đặt điểm ngắt khi xây dựng 'b' bởi hàm tạo bản sao. Đầu ra của trình lắp ráp tại điểm đó trong trình gỡ lỗi VC++ 6 là:
12: A b(a);
00401195 lea eax,[ebp-1B0h]
0040119B push eax
0040119C lea ecx,[ebp-354h]
004011A2 call @ILT+140(A::A) (00401091)
Cuối cùng là lệnh gọi hàm sao chép. Bạn cũng có thể theo dõi điều đó nếu bạn muốn biết thêm chi tiết. Tuy nhiên, nếu câu hỏi của bạn là "làm thế nào tôi có thể nhìn thấy mã C++ cho nhà xây dựng sao chép et al", câu trả lời là bạn không thể, bởi vì không có bất kỳ - trình biên dịch tạo ra bộ mã hóa hoặc mã máy (tùy thuộc vào tùy chọn này.). trên trình biên dịch của bạn) cho họ, không phải mã C++.
Bạn có chắc chắn cần xem các chức năng này không?
Theo mặc định, Trình biên dịch tạo chúng bằng cách gọi toán tử Constructor hoặc Assignment trên mỗi biến thành viên.
Vấn đề với điều đó là khi bạn sử dụng các đối tượng sử dụng tham chiếu Đếm để quản lý dữ liệu, Trình tạo bản sao mặc định sẽ tạo bản sao của đối tượng chứ không phải bản sao của Dữ liệu mà đối tượng trỏ tới. Đây cũng là trường hợp cho con trỏ.Vì vậy, nếu bạn có một lớp học như:
class aClass
{
int one;
int *ptwo;
};
Trình tạo bản sao mặc định chỉ sao chép dữ liệu a và con trỏ b. Tuy nhiên, anh ta không sao chép dữ liệu được chỉ ra bởi b. Nếu bạn sử dụng lớp học này như
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
Nếu bạn muốn lớp này sao chép giá trị ptwo thay vì con trỏ, bạn sẽ cần chức năng điều hành gán bản sao của riêng bạn. Nếu bạn quan tâm đến chi tiết hơn những gì các chức năng mặc định làm và những gì không thì bạn hãy xem vào cuốn sách "Hiệu quả C + +".
Nó có toàn bộ một chương về công cụ này, giải thích những chức năng mặc định của lớp học, không làm, những gì họ nên làm, khi nào để viết của riêng bạn. Tôi chắc chắn bạn có thể tải phiên bản kỹ thuật số trên web nếu bạn chỉ muốn biết về chức năng này.
Trình biên dịch tạo ra các phương thức trừu tượng không tồn tại trong mã nguồn.
Hãy xem ví dụ bên dưới, tôi thử và giải thích những gì bốn phương thức tạo biên dịch có nghĩa vụ phải làm ở cấp mã nguồn. Từ đó bạn sẽ có thể ngoại suy bất kỳ lớp bình thường nào.
Nếu bạn có một lớp học như thế này:
class X: public Base
{
int* a;
double b;
Y c;
};
Sau đó trình biên dịch tạo ra tương đương với các nội dung sau:
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;
}
Xem thêm: http://stackoverflow.com/a/1810320/14065 –
- 1. Tạo danh sách các macro tiền xử lý được xác định bởi trình biên dịch
- 2. Các trình biên dịch loại bỏ các chức năng, định nghĩa, biến, macro, bao gồm vv
- 3. C++: Trình biên dịch và chức năng Trình liên kết
- 4. Thay đổi Trình biên dịch Mặc định Trong Emacs?
- 5. gcc 4.3.3 tùy chọn trình biên dịch được bật theo mặc định
- 6. Cảnh báo trình biên dịch này được tạo ra bởi `-pedantic` có nghĩa là gì?
- 7. Hằng số không được tải bởi trình biên dịch
- 8. Cờ biên dịch mặc định với Autotools
- 9. Đặt trình biên dịch mặc định trong CMake
- 10. constexpr tĩnh trỏ-to-chức năng, sự khác biệt giữa các trình biên dịch
- 11. trình biên dịch tạo nhà xây dựng
- 12. Chuyển tiếp tuyên bố của lớp được sử dụng trong mẫu chức năng không được biên dịch bởi kêu vang ++
- 13. Tại sao NULL không được xác định trước bởi trình biên dịch
- 14. Trình biên dịch/trình biên dịch/trình biên dịch C++
- 15. Chức năng đối số mặc định và tiêu đề
- 16. GCC - Chỉ kích hoạt cờ trình biên dịch trên các chức năng cụ thể
- 17. Các khối Objective-C có được hỗ trợ bởi các trình biên dịch trên Linux không?
- 18. Làm thế nào tôi có thể xem mã lắp ráp được tạo bởi trình biên dịch gcc (bất kỳ hương vị) nào cho chương trình C/C++?
- 19. Cách tạo trình xem html mặc định chrome trên android
- 20. Các tham số mặc định để hạn chế các chức năng (amp)
- 21. Trình tạo mặc định có khởi tạo các kiểu dựng sẵn không?
- 22. GCC biên dịch có tài liệu tham khảo không xác định mặc dù trước đây chức năng liên kết Ubuntu
- 23. giá trị đối tượng mặc định trong chức năng với đối số mặc định giá trị
- 24. MongoDB nhóm bởi Các chức năng
- 25. Tại sao trình biên dịch chọn chức năng mẫu này trên một chức năng không mẫu quá tải?
- 26. Các tính năng của ngôn ngữ thông dịch nào có thể được biên dịch?
- 27. Gọi đến chức năng template thành viên không biên dịch
- 28. UnicodeEncodeError khi sử dụng chức năng biên dịch
- 29. Tại sao MSVC không biên dịch được chức năng mẫu này?
- 30. Tại sao trình biên dịch tạo ra assembly này?
Dường như có một số nhầm lẫn về câu hỏi của bạn. Bạn có nghĩa là làm thế nào để tôi xem các nguyên mẫu chức năng, làm thế nào để tôi nhìn thấy được mặc định và tôi đã thực hiện, hoặc làm thế nào để tôi thấy mã cho việc triển khai mặc định? –