Câu trả lời ngắn - không làm điều đó.
chi tiết:
// copy constructor
FeatureValue::FeatureValue(const FeatureValue& other)
{
m_size = other.m_size;
delete[] m_value; // m_value NOT INITIALISED - DON'T DELETE HERE!
m_value = new uint8_t[m_size];
for (int i = 0; i < m_size; i++)
{
m_value[i] = other.m_value[i];
}
}
// assignment operator function
FeatureValue& FeatureValue::operator=(const FeatureValue& other)
{
FeatureValue(other); // error C2082: redefinition of formal parameter
return *this;
}
Ghi chú:
- Khi copy constructor được gọi, nó xây dựng các đối tượng mới với tham chiếu đến các đối tượng được sao chép, nhưng các nhà xây dựng mặc định không chạy trước copy constructor. Điều này có nghĩa là
m_value
có giá trị không xác định khi hàm khởi tạo sao chép bắt đầu chạy - bạn có thể gán cho nó, nhưng để đọc từ đó là hành vi không xác định, và đến delete[]
nó tệ hơn nhiều (nếu có điều gì tệ hơn UD! ;-)). Vì vậy, chỉ cần bỏ ra rằng delete[]
dòng.
Tiếp theo, nếu operator=
cố gắng tận dụng chức năng từ trình tạo bản sao, trước tiên phải phát hành mọi dữ liệu hiện có m_value
đang trỏ hoặc sẽ bị rò rỉ. Hầu hết mọi người cố gắng làm điều đó như sau (mà được chia) - Tôi nghĩ rằng đây là những gì bạn đang cố gắng cho:
FeatureValue& FeatureValue::operator=(const FeatureValue& other)
{
// WARNING - this code's not exception safe...!
~FeatureValue(); // call own destructor
new (this) FeatureValue(other); // reconstruct object
return *this;
}
Vấn đề ở đây là nếu việc tạo ra các FeatureValue không (ví dụ vì new
thể không nhận được bộ nhớ nó muốn), sau đó các đối tượng FeatureValue
là trái với một nhà nước không hợp lệ (ví dụ: m_value
có thể được chỉ ra vào không gian). Sau đó khi destructor chạy và thực hiện delete[] m_value
, bạn có hành vi không xác định (chương trình của bạn có thể sẽ bị lỗi).
Bạn thực sự nên tiếp cận điều này một cách có hệ thống hơn ...hoặc viết nó ra từng bước, hoặc có lẽ thực hiện một đảm bảo không ném phương pháp swap()
(dễ dàng để làm ... chỉ std::swap()
m_size
và m_value
, và sử dụng nó ala:
FeatureValue& FeatureValue::operator=(FeatureValue other)
{
swap(other);
return *this;
}
Đó là dễ dàng và sạch sẽ, nhưng nó có một cặp vợ chồng nhỏ vấn đề hiệu suất/hiệu quả:
giữ bất kỳ m_value
mảng hiện xung quanh lâu hơn cần thiết, tăng sử dụng bộ nhớ cao điểm ... bạn có thể gọi clear()
Trong thực tế, hầu hết các chương trình không tầm thường sẽ không quan tâm. về điều này trừ khi dat một cấu trúc được đề cập đang chứa lượng dữ liệu khổng lồ (ví dụ: hàng trăm megabyte hoặc gigabyte cho một ứng dụng PC).
thậm chí không cố gắng sử dụng lại bộ nhớ hiện tại m_value
- thay vào đó luôn thực hiện new
khác cho other
(có thể dẫn đến giảm mức sử dụng bộ nhớ nhưng không phải lúc nào cũng đáng giá).
Cuối cùng, lý do có thể có khác biệt constructor sao chép và operator=
- thay vì phải trình biên dịch tự động tạo ra một từ khác - đó là triển khai một cách tối ưu hiệu quả có thể không - nói chung - đòn bẩy nhau trong cách bạn đã hy vọng.
Nguồn
2013-07-05 03:05:45
tại sao không chỉ 'm_value [i] = other.m_value [i]' thay vì sử dụng giá trị trung gian, ví dụ: 'value [i] = other.m_value [i]'? – stackunderflow