2011-08-24 30 views
6

Bối cảnh: Tôi có một lớp phức tạp với nhiều biến. Tôi có công cụ tạo bản sao âm thanh và thử nghiệm:Tôi có thể sử dụng vị trí mới (điều này) trong toán tử =?

Applepie::Applepie(const Applepie &copy) : 
m_crust(copy.m_crust), 
m_filling(copy.m_filling) 
{ 
} 

Một số nhà xây dựng bản sao biến thành viên được gọi trong danh sách intializer thực hiện phân bổ.

Câu hỏi: Tôi cần tạo operator=. Thay vì nhân đôi constuctor hiện với nhiệm vụ thay vì danh sách khởi tạo, và giải phóng bộ nhớ đang được thay thế, và vv vv vv, tôi có thể chỉ đơn giản là làm như sau:

Applepie& Applepie::operator=(const Applepie &copy) 
{ 
    if(this != &copy) 
    { 
     this->~Applepie(); // release own object 
     new(this) Applepie(copy); // placement new copy constructor 
    } 
    return *this; 
} 

Nói cách khác, là phá hủy tự tiếp theo là một vị trí new constructor sao chép ngữ nghĩa giống hệt với toán tử =?

Điều này dường như có khả năng làm giảm đáng kể mã lặp lại và xác nhận rằng mỗi biến được khởi tạo đúng cách, với chi phí tiềm năng giảm nhẹ hiệu quả trong quá trình gán. Tôi có thiếu cái gì đó mơ hồ hơn không?

Lý do: Lớp thực tế của tôi có khoảng 30 biến. Tôi lo lắng về thực tế là cả hai nhà xây dựng bản sao của tôi và nhà điều hành chuyển nhượng của tôi phải sao chép tất cả ba mươi, và rằng mã có thể phân kỳ, làm cho hai hoạt động để làm những việc khác nhau.

+4

Nếu ctor sao chép ném, bạn đã phá vỡ đối tượng, do đó, bạn không đưa ra bất kỳ đảm bảo an toàn kỳ vọng nào. –

+1

@R Martinho - Dường như với tôi rằng bất kỳ tình huống nào trong đó bản sao ctor sẽ ném cũng sẽ khiến toán tử của tôi = ném nếu tôi được gán thủ công mỗi biến ... Vậy ... điều đó vẫn có vẻ tương đương? – jcwenger

+3

vấn đề không phải là 'toán tử =' ném, là 'toán tử =' rời khỏi đối tượng trong trạng thái không hợp lệ! Nó đã bị phá hủy. –

Trả lời

6

Vì Herb Sutter ở trạng thái "Ngoại lệ C++", nó không phải là ngoại lệ an toàn. Điều đó có nghĩa, nếu bất cứ điều gì là sai trong khi new hoặc xây dựng đối tượng mới, toán hạng bên trái của nhiệm vụ ở trạng thái xấu (không xác định), hãy gọi cho nhiều rắc rối hơn. Tôi thực sự khuyên bạn nên sử dụng số copy & swap idiom.

Applepie& Applepie::operator=(Applepie copy) 
{ 
    swap(m_crust, copy.m_crust); 
    swap(m_filling, copy.m_filling); 
    return *this; 
} 

Khi đối tượng của bạn sử dụng Pimpl ngữ (con trỏ tới thực hiện) cũng có, những trao đổi được thực hiện bằng cách thay đổi chỉ có hai con trỏ.

+1

+1 'swap' là một giá trị thấp tuyệt vời chức năng ... lợi thế bổ sung: trình biên dịch có thể thực hiện sao chép elision nếu đối số là một rvalue. –

+0

Vì vậy ... Vấn đề của tôi với điều này là lớp thực tế của tôi có khoảng 30 biến. Trình tạo bản sao của tôi có tất cả 30 biến trong danh sách trình khởi tạo. sao chép và trao đổi vẫn sẽ yêu cầu tôi có 30 cuộc gọi hoán đổi() - đối tượng của tôi là giảm khả năng Applepie pie (bản gốc); và táo Applepie; apple = bản gốc; tạo ra các kết quả khác nhau. – jcwenger

+0

@jcwenger: Vâng, đó là một lời kêu gọi rắc rối. Vì vậy, nó có thể là một ứng cử viên cho thành ngữ * Pimpl *, nhưng trước khi chuyển sang đó, xem xét nó đang đến với chi phí: mỗi thành viên truy cập sẽ đi qua một con trỏ sau đó. Một ý tưởng khác là chia lớp 'Applepie' thành những phần nhỏ hơn. Nếu bạn có 30 thành viên dữ liệu trong một lớp, có thể có sự cố với thiết kế ... –

0

Ngoài câu trả lời của Rene, còn có vấn đề xảy ra nếu ApplePie là lớp cơ sở của đối tượng thực tế: ApplePie sẽ thay thế đối tượng bằng đối tượng sai loại!

+1

Toán tử = sẽ làm * đối tượng cắt * anyway, nếu đối tượng không được triển khai trong thành phần Xử lý-Công nhân. –

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