2012-01-10 44 views
5

thể trùng lặp:
Why copy constructor is not called in this case?Sao chép Constructor không gọi

Hãy xem xét các chương trình mẫu dưới đây:

#include <iostream> 

using namespace std; 

class sample 
{ 
    private: 
     int x; 

    public: 
     sample(int a=0) : x(a) 
     { 
      cout << "default ctor invoked\n"; 
     } 

     sample(const sample& obj) 
     { 
      cout << "copy ctor invoked\n"; 
     } 

}; 

int main() 
{ 
    sample s2 = sample(20); //Line1 
    sample s3 = 20; //Line2 

    return 0; 
} 

Trong Line1, đầu tiên các nhà xây dựng của sample lớp được gọi explicitly với đối số 20. Sau đó, tôi mong đợi constructor sao chép được gọi để khởi tạo s2.

Trong dòng 2, đầu tiên hàm tạo của lớp sample được gọi implicitly đầu tiên với đối số 20. Ở đây tôi cũng mong đợi trình tạo bản sao được gọi để khởi tạo s2.

Trong cả hai trường hợp, hàm tạo bản sao không được gọi? Tại sao chuyện này đang xảy ra? Tôi tin rằng, có điều gì đó sai trái với sự hiểu biết của tôi về sự kêu gọi của nhà xây dựng bản sao. Ai đó có thể sửa tôi, nơi tôi đang đi sai?

+0

Điều này được mong đợi - hãy để tôi thử và tìm một ví dụ tốt –

+0

Các cuộc gọi đến trình tạo bản sao có thể được ưu tiên trong một số trường hợp. –

+0

@ R.MartinhoFernandes: Ya một số tình huống. Nhưng s2 và s3 phải được khởi tạo một cách nào đó. Làm thế nào là nó được thực hiện mà không cần gọi ctor sao chép? –

Trả lời

8

Điều này được mong đợi. Nó được gọi là copy elision.

Kỳ vọng của bạn là chính xác, nhưng họ đã thực hiện ngoại lệ trong C++ (để thực hiện) cho phép trình biên dịch coi biểu thức của bạn là khởi tạo trực tiếp một thể hiện trong khi bỏ qua trình tạo bản sao.

+0

Đối với phiên bản đầu tiên có, trình biên dịch có thể quyết định thực hiện sao chép elision hoặc không làm như vậy. Nhưng tôi nghĩ rằng trong dòng thứ hai, 'sample s3 = 20;', thì trình biên dịch * phải * chỉ cần gọi hàm tạo 'int'. Tôi nghĩ rằng tôi đang yêu cầu "là sao chép elision * tùy chọn * trong cả hai trường hợp?" –

+1

Cả hai sẽ không hoạt động nếu hàm tạo bản sao không truy cập được (tức là 'riêng tư ') hoặc bị xóa. Vì vậy, nó không phải là * chính xác * được coi là khởi tạo trực tiếp. –

+0

cả hai đều yêu cầu khởi tạo sao chép. cả hai đều tương đương với 'mẫu s (mẫu (20));'. bạn có thể chứng minh điều này bằng cách biên dịch sau khi tạo bản sao ctor riêng. sao chép elision là không bao giờ yêu cầu. nó được * cho phép * theo tiêu chuẩn để tối ưu hóa trình biên dịch. cho dù đó là elided hay không là lên đến trình biên dịch của bạn (s). – justin

0

trong dòng đầu tiên nó không gọi hàm tạo bản sao vì bạn không sao chép một đối tượng. Bạn đang gán một đối tượng cho một đối tượng khác. C++ cung cấp toán tử mặc định = thực hiện sao chép nông. Và điều này được gọi ngầm. Hàm khởi tạo được gọi cho đối tượng tay phải và hàm tạo mặc định được gọi cho đối tượng bên trái. Sau đó toán tử default = được gọi.

Đối với dòng 2, nó sử dụng hàm tạo có tham số int mà bạn xác định. Nó thực sự là công cụ chuyển đổi bởi vì nó lấy một số nguyên và tạo đối tượng của lớp của bạn. Thats lý do tại sao c + + sử dụng điều này như là một nhà xây dựng chuyển đổi và khi bạn cố gắng để chỉ định một số nguyên cho đối tượng của bạn, C++ invokes inplicitly này constructor chuyển đổi.

Tôi hy vọng điều này sẽ giúp bạn hiểu.

+0

Cemal: Giải thích của bạn về Line1 không đúng, tôi nghĩ vậy. Như tôi đã hiểu từ những người khác đã đưa ra câu trả lời và nhận xét, cả Line1 và Line2 đều khởi tạo bản sao, nhưng trình biên dịch tối ưu hóa nó để khởi tạo trực tiếp bằng cách ngăn chặn gọi hàm tạo bản sao. –

+1

Có bạn có quyền. Nói chung nó sử dụng constructor sao chép khi bạn sử dụng = toán tử nhưng tôi đã không nhận ra theo văn bản người hỏi hỏi. Như bạn đã nói tôi không nghĩ về tối ưu hóa trình biên dịch và suy nghĩ trực tiếp. Cảm ơn bạn đã cảnh báo –

Các vấn đề liên quan