Sử dụng biến trong bộ khởi tạo riêng


22

[basic.scope.pdecl] / 1 của dự thảo tiêu chuẩn C ++ 20 có ví dụ (không quy định) sau trong một ghi chú (trích dẫn một phần từ trước khi hợp nhất yêu cầu kéo 3580 , xem câu trả lời cho câu hỏi này):

unsigned char x = x;

[...] x được khởi tạo với giá trị (không xác định) của chính nó.

Điều này thực sự có hành vi được xác định rõ trong C ++ 20?


Nói chung, việc tự khởi tạo biểu mẫu T x = x;có hành vi không xác định do xgiá trị của không xác định trước khi hoàn thành khởi tạo. Đánh giá các giá trị không xác định thường gây ra hành vi không xác định ( [basic.indent] / 2 ), nhưng có một ngoại lệ cụ thể trong [basic.indent] /2.3 cho phép khởi tạo trực tiếp một unsigned charbiến từ một giá trị unsigned charkhông xác định (gây ra khởi tạo với giá trị không xác định ).

Do đó, điều này một mình không gây ra hành vi không xác định, nhưng đối với các loại khác Tkhông phải là loại ký tự hẹp không dấu hoặc std::byte, ví dụ int x = x;. Những cân nhắc này được áp dụng trong C ++ 17 và trước đó, xem thêm các câu hỏi được liên kết ở phía dưới.

Tuy nhiên, ngay cả đối với unsigned char x = x;, bản dự thảo hiện tại [basic.lifetime] / 7 nói:

Tương tự, trước khi thời gian tồn tại của một đối tượng đã bắt đầu [...] bằng cách sử dụng các thuộc tính của giá trị không phụ thuộc vào giá trị của nó được xác định rõ. Chương trình có hành vi không xác định nếu:

  • glvalue được sử dụng để truy cập vào đối tượng, hoặc

  • [...]

Điều này dường như ngụ ý rằng xgiá trị trong ví dụ chỉ có thể được sử dụng trong suốt vòng đời của nó.

[basic.lifetime] / 1 nói:

[...]

Thời gian tồn tại của một đối tượng loại T bắt đầu khi:

  • [...] Và
  • khởi tạo của nó (nếu có) đã hoàn tất (bao gồm cả khởi tạo trống) ([dcl.init]),

[...]

Do đó x, cuộc đời chỉ bắt đầu sau khi hoàn thành khởi tạo. Nhưng trong xgiá trị của ví dụ được trích dẫn được sử dụng trước khi quá trình xkhởi tạo hoàn tất. Do đó việc sử dụng có hành vi không xác định.

Phân tích của tôi có đúng không và nếu có, nó có ảnh hưởng đến các trường hợp sử dụng trước khi khởi tạo không, chẳng hạn như

int x = (x = 1);

mà theo như tôi có thể nói, được xác định rõ trong C ++ 17 và trước đó thì sao?


Lưu ý rằng trong C ++ 17 (bản nháp cuối cùng), yêu cầu thứ hai để bắt đầu trọn đời là khác nhau :

  • nếu đối tượng có khởi tạo không trống, việc khởi tạo của nó hoàn tất,

xsẽ có khởi tạo trống theo định nghĩa của C ++ 17 (nhưng không phải là khởi tạo trong bản nháp hiện tại), nên thời gian tồn tại của nó đã bắt đầu khi nó được truy cập trong trình khởi tạo trong các ví dụ nêu trên và vì vậy trong cả hai ví dụ không có hành vi không xác định do thời gian tồn xtại của C ++ 17.

Từ ngữ trước C ++ 17 lại khác, nhưng có cùng kết quả.


Câu hỏi không phải là về hành vi không xác định khi sử dụng các giá trị không xác định, được nêu trong ví dụ: các câu hỏi sau:


@L LanguageLawyer Tôi không tự tin rằng mình đúng, đặc biệt là không nếu chưa có ai trả lời. Nếu những người khác sẽ đồng ý với tôi ở đây, tôi có thể nộp đơn sau (hoặc có thể người khác sẽ trước tôi), nhưng tôi không muốn gửi các vấn đề mà tôi không chắc chắn.
quả óc chó

@L LanguageLawyer: Không thể là vấn đề biên tập nếu bài viết làm việc rõ ràng nói sai.
Davis Herring

1
Từ được thay đổi bởi P1353 .
xskxzr

1
@xskxzr Phải, và trong thời gian đó LanguageLawyer cũng đã nộp một vấn đề biên tập , dường như đã được chuyển đến CWG để làm rõ ý định.
quả óc chó

1
@ clockw0rk int x ^= x;không được hình thành tốt về mặt cú pháp. Bạn có thể có một định nghĩa biến với trình khởi tạo (nghĩa là int x = x;mặc dù là UB) hoặc câu lệnh biểu thức gán xor (nghĩa là x ^= x;mặc dù đó là UB nếu xthuộc loại int, được khởi tạo mặc định và không được gán trước). Bạn không thể trộn hai thứ này thành một.
quả óc chó

Câu trả lời:


8

Điều này đã được mở như là một vấn đề biên tập . Nó đã được chuyển đến CWG để thảo luận (nội bộ). Khoảng 24 giờ sau, người chuyển tiếp vấn đề đã tạo một yêu cầu kéo để sửa đổi ví dụ để làm rõ rằng đây là UB:

Ở đây, việc khởi tạo \ tcode {x} thứ hai có hành vi không xác định, bởi vì trình khởi tạo truy cập \ tcode {x} thứ hai bên ngoài vòng đời của nó \ iref {basic.life}.

Đó là PR đã được thêm vào và vấn đề đóng cửa. Vì vậy, có vẻ như rõ ràng rằng giải thích rõ ràng (UB do truy cập một đối tượng mà cả đời chưa bắt đầu) là giải thích dự định. Dường như mục đích của ủy ban làm cho các cấu trúc này không hoạt động và văn bản phi quy phạm của tiêu chuẩn đã được cập nhật để phản ánh điều này.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.