2011-10-06 31 views
18

Với C++ mã sau:Strange GCC Behavior

struct vertex_type { 
    float x, y, z; 

    //vertex_type() {} 
    //vertex_type(float x, float y, float z) : x(x), y(y), z(z) {} 
}; 

typedef struct { 
    vertex_type vertex[10000]; 
} obj_type; 

obj_type cube = { 
    { 
     {-1, -1, -1}, 
     {1, -1, -1}, 
     {-1, 1, -1}, 
     {1, 1, -1}, 

     {-1, -1, 1}, 
     {1, -1, 1}, 
     {-1, 1, 1}, 
     {1, 1, 1} 
    } 
}; 

int main() { 
    return 0; 
} 

Khi tôi thêm (hiện nhận xét ra) nhà xây dựng vào vertex_type struct, nó đột ngột 10-15 tăng thứ hai trong thời gian biên dịch. Stumped, tôi nhìn vào lắp ráp được tạo ra bởi gcc (sử dụng -S), và nhận thấy rằng kích thước mã gen là lớn hơn vài trăm lần so với trước đây.

... 
movl $0x3f800000, cube+84(%rip) 
movl $0x3f800000, cube+88(%rip) 
movl $0x3f800000, cube+92(%rip) 
movl $0x00000000, cube+96(%rip) 
... 
movl $0x00000000, cube+119996(%rip) 
... 

Bằng cách bỏ định nghĩa hàm tạo, hội đồng được tạo khác hoàn toàn.

.globl cube 
    .data 
    .align 32 
    .type cube, @object 
    .size cube, 120 
cube: 
    .long 3212836864 
    .long 3212836864 
    .long 3212836864 
    .long 1065353216 
    .long 3212836864 
    .long 3212836864 
    .long 3212836864 
    .long 1065353216 
    .long 3212836864 
    .long 1065353216 
    .long 1065353216 
    .long 3212836864 
    .long 3212836864 
    .long 3212836864 
    .long 1065353216 
    .long 1065353216 
    .long 3212836864 
    .long 1065353216 
    .long 3212836864 
    .long 1065353216 
    .long 1065353216 
    .long 1065353216 
    .long 1065353216 
    .long 1065353216 
    .zero 24 
    .text 

Rõ ràng có sự khác biệt đáng kể trong mã do trình biên dịch tạo ra. Tại sao vậy? Ngoài ra, tại sao gcc không phải tất cả các phần tử trong một tình huống và không phải là yếu tố khác?

chỉnh sửa: Tôi đang sử dụng cờ trình biên dịch sau: -std=c++0x với g ++ 4.5.2.

+0

Đây là một dự đoán hoang dã, nhưng hãy thử điều này: vertex_type(): x(), y(), z() {} – Pubby

+4

@ AlfP.Steinbach Đây là chính xác mã tôi có trong hồ sơ của mình. Không có gì khác cả. Bạn đã kiểm tra mã chưa? Nó có {}. Nó là nội tuyến ... – dcousens

+3

@Alf các nhà thầu trong câu hỏi được nhận xét. – zwol

Trả lời

14

Đây là một dài hạn missing optimization in GCC. Nó nên có thể tạo cùng mã cho cả hai trường hợp, nhưng không thể.

Không có nhà thầu, vertex_type của bạn là cấu trúc POD, mà GCC có thể khởi tạo các trường hợp tĩnh/toàn cục của thời gian biên dịch. Với các nhà xây dựng, tốt nhất nó có thể làm là tạo ra mã để khởi tạo toàn cầu khi khởi động chương trình.

+1

Cảm ơn thông tin chi tiết và liên kết, nhưng tại sao nó không phải là các phần tử còn lại trong một trường hợp chứ không phải phần tử còn lại? – dcousens

+0

Câu trả lời này không chính xác. Mã với hàm tạo nên không biên dịch. Xem câu trả lời của tôi. – Nawaz

+0

@Daniel Đó có thể là lỗi (không liên quan). Bản sao của tôi của g ++ 4.6.1 zeroes các yếu tố còn lại trong cả hai trường hợp (và cũng * không * tạo ra 9976 'movl' hướng dẫn để điền vào các zeroes - nó sử dụng' .bss' để làm điều đó ngầm). Tôi không có gcc 4.5. – zwol

0

Nếu bạn có hàm tạo tùy chỉnh, trình biên dịch nên gọi nó cho tất cả các vectơ mà nó tạo ra. Nếu bạn không viết của riêng bạn, nó mặc định để tạo ra một nhà xây dựng. Nhưng không có loại nào phức tạp, nó không cần phải gọi nó. Và mảng được lưu trữ dưới dạng một bảng không đổi trong nhị phân.

Thử nội tuyến hàm tạo mặc định của bạn và để trống. Tất nhiên, nó chỉ có thể hoạt động tối ưu hóa hit h2 được kích hoạt

+1

Nó không thể inline một constructor mặc định như xa như tôi biết. Mã ông đăng các nhà xây dựng là hoàn toàn nội tuyến. – Pubby

+0

Có thể sử dụng phần mở rộng của trình biên dịch như __forceinline trong MSVC – crazyjul