2015-12-23 15 views
20

Một POD struct có thể zero-khởi tạo trong C++ 11 như sau:Zero-reinitializing một struct trong C++

SomeStruct s{}; 

Tuy nhiên, tôi phải làm gì nếu tôi đã có một thể hiện của các struct và tôi muốn khởi tạo lại nó về số không? Công việc sau dường như hoạt động:

s = {}; 

Ai đó có thể chỉ ra tiêu chuẩn có liên quan? Tôi cho rằng đây là những gì đang xảy ra:

  1. Ví dụ mới được khởi tạo bằng không được tạo.
  2. Ví dụ mới được gán cho cá thể hiện có, gọi toán tử gán ngầm.
+1

Tôi không biết về tiêu chuẩn, nhưng - một số điều này có thể được tối ưu hóa. Trong thực tế, nếu bạn không sử dụng của 0, có thể _all_ của điều này được tối ưu hóa đi. – einpoklum

+1

Có một quy tắc rõ ràng trong đó cho phép niềng răng ở bên phải của một bài tập. Giả định của bạn khá chính xác. – chris

+0

Không có điều gì như "khởi tạo lại". Bạn khởi tạo một cái gì đó một lần. Chỉ một lần. Những gì bạn đang làm là phân công và rất khác nhau theo những cách tinh tế và không quá tinh tế. –

Trả lời

18

gì bạn đang tìm kiếm là trong [expr.ass]

Một chuẩn bị tinh thần-init-list có thể xuất hiện ở phía bên tay phải của

  • một sự ủy thác một vô hướng, trong trường hợp danh sách bộ khởi tạo sẽ có nhiều nhất một phần tử đơn. Ý nghĩa của là x={v}, trong đó T là loại vô hướng của biểu thức x, là của x=T{v}. Ý nghĩa của x={}x=T{}.
  • một nhiệm vụ cho một đối tượng thuộc loại lớp, trong trường hợp danh sách bộ khởi tạo được chuyển làm đối số cho chức năng điều hành gán được chọn theo độ phân giải quá tải (13.5.3, 13.3).

Vì vậy, dự đoán của bạn là chính xác. Trình biên dịch có thể có thể tối ưu hóa mọi thứ nhưng bạn có thể nghĩ về nó như tạo ra một tạm thời không được khởi tạo và chuyển nó tới operator=.

12

s = {}; không an toàn.

Vấn đề là bạn hy vọng biến thành s = SomeStruct{};. Tuy nhiên, nếu s có tình trạng quá tải khác cho operator=then that may be preferred by overload resolution.

Vì vậy, đây thực sự là một mẫu chống. Như đã đề cập trên các chủ đề khác, bạn nên viết một hàm, ví dụ .:

template<typename T> void reset(T &t) { t = T{}; } 

Tôi đoán bạn cũng có thể viết s = decltype(s){};, chừng nào s không phải là một tài liệu tham khảo.

+1

Tại sao không sử dụng 'hy vọng' cho độ phân giải một cách rõ ràng. 's = SomeStruct {}'? Điều đó có vẻ rõ ràng hơn một hàm gọi tới 'reset()'. –

+1

@LokiAstari tốt, chúng ta có thể cách xa sự tuyên bố của 's' vì vậy nó không phải dễ dàng như vậy để kiểm tra rằng điều này thực sự làm điều đúng. Nếu chúng ta vô tình đặt 's = SomeOtherStruct {};' thì các hiệu ứng kỳ lạ khác có thể xảy ra. Tôi cố gắng sử dụng các mẫu mã giúp giảm thiểu khả năng mắc lỗi (đặc biệt là các lỗi không rõ ràng). Tôi đoán phiên bản 'decltype' là tốt nhất. Tôi thấy rằng không thẩm mỹ nhưng có lẽ tôi cần cập nhật thẩm mỹ của mình –

+0

Tôi lấy ý kiến ​​của bạn về 'SomeOtherStruct {}'. Sau đó, nó có ý nghĩa hơn cho 'decltype' nhưng điều đó vẫn trông xấu xí (và thẩm mỹ là quan trọng). –