2012-02-29 11 views
6

Tại sao đầu ra của chương trình sau chỉ int3 và không phải là int3&4?Sao chép hàm tạo với tham số mặc định không bao giờ được gọi là

#include <iostream> 

class B 
{ 
public: 
    explicit B(int i) { std::cout<<"int"<<i; } 
    B(const B& rhs, int i = 0) { std::cout<<"&"<<i; } 
}; 

int main(int, char**) 
{ 
    B b(B(3), 4); 
} 

Command: clang++ test.cpp -O0

Compiler: Apple phiên bản kêu vang 3.0 (thẻ/Apple/kêu vang-211,12) (dựa trên LLVM 3.0svn)

+0

Nó in 'int3 & 4' cho tôi (GCC 4.6.2,' -O3'). –

+0

Trên thực tế, g ++ 4.6.1 của tôi in "int3 & 4". – Duck

+1

+1 cho trường hợp kiểm tra ngắn, đầy đủ. http://sscce.org –

Trả lời

1

Đây là một bug in clang, có since been fixed. Copy-elision đã được áp dụng không đúng cho lời gọi hàm tạo, bởi vì clang không kiểm tra xem có bao nhiêu đối số được cung cấp trước khi kết luận rằng nó là một bản sao xây dựng.

Bản sửa lỗi sẽ nằm trong bản phát hành sắp tới 3.1.

3

Hình như bạn có thể đã tìm thấy một đứa biên dịch:)

Nếu bạn thay đổi phiên bản trình biên dịch của bạn để bất cứ điều gì đó không phải là LLVM 3.0, đầu ra là int3 & 4.

in này i NT3 & 4 trên LLVM 3.0, vì vậy có vẻ như có liên quan đến thực tế là B (3) là một đối tượng tạm thời:

class B 
{ 
public: 
    explicit B(int i) 
    { 
     std::cout<<"int"<<i; 
    } 
    B(const B& rhs, int i = 0) 
    { 
     std::cout<<"&"<<i; 
    } 
}; 

int main(int, char**) 
{ 
    B a(3); 
    B b(a, 4); 
} 
+0

Vâng, đây là một lỗi trong tiếng kêu vang, từ đó đã được sửa. Copy-elision đã được áp dụng không đúng cho lời gọi hàm tạo, bởi vì clang không kiểm tra xem có bao nhiêu đối số được cung cấp trước khi kết luận rằng nó là một bản sao xây dựng. –

+0

@RichardSmith Bạn có thể đăng nhận xét này làm câu trả lời không? –

0

Nhiều khả năng, RVO và NRVO ăn mã của bạn. Những điều kiện đặc biệt này cho phép trình biên dịch âm thầm loại bỏ các bản sao đối tượng mà nếu không sẽ được thực thi bởi ngôn ngữ. Vì không có bản sao nào được tạo ra, nên mã không bao giờ in câu lệnh trong hàm tạo bản sao.

+0

Có thể cho phép RVO và NRVO ngay cả trong chế độ Gỡ lỗi không? Theo tôi hiểu nó, họ là tối ưu hóa và do đó nên được vô hiệu hóa khi chạy trong chế độ Debug, nhưng trong chế độ Debug tôi nhận được "int3" quá, trên LLVM 3.0 – Carl

+0

Chỉ cần nghĩ rằng tôi muốn thêm này: http://stackoverflow.com/ câu hỏi/8556608/what-can-i-reasonably-expect-a-compiler-to-be-can-in-inline. Rõ ràng, một số trình biên dịch có chọn lọc thực hiện RVO và/hoặc NRVO trong chế độ gỡ lỗi quá, mà sẽ giải thích hành vi của LLVM. – Carl

+0

@carleeto: Trình biên dịch có thể hợp pháp làm điều đó bất cứ khi nào nó thích. – Puppy