Mã của bạn gọi UB, nhưng không phải vì lý do launder
. Đó là bởi vì p0[1].i
chính là UB.
Vâng, thực sự ([Expr.Add]/4):
Khi một biểu thức có kiểu không thể thiếu được thêm vào hoặc trừ từ một con trỏ, kết quả có kiểu của toán hạng trỏ. Nếu biểu thức P trỏ đến phần tử x [i] của một đối tượng mảng x với các phần tử n, các biểu thức P + J và J + P (trong đó J có giá trị j) trỏ đến phần tử (có thể giả định) x [i + j] nếu 0 ≤ i + j ≤ n; nếu không, hành vi là không xác định. Tương tự như vậy, biểu thức P - J trỏ tới phần tử (có thể giả thiết) x [i - j] nếu 0 ≤ i - j ≤ n; nếu không, hành vi là không xác định.
Một đối tượng không phải là phần tử mảng được coi là thuộc về mảng đơn nguyên tố cho mục đích này; xem 8.3.1. Một con trỏ qua phần tử cuối cùng của một mảng x của n phần tử được coi là tương đương với một con trỏ tới một phần tử giả thuyết x [n] cho mục đích này; xem 6.9.2.
[]
khi áp dụng cho con trỏ có nghĩa là làm số học con trỏ. Và trong mô hình đối tượng C++, số học con trỏ chỉ có thể được sử dụng trên con trỏ tới các phần tử trong một mảng của kiểu được trỏ tới. Bạn luôn có thể coi một đối tượng là một mảng có độ dài 1, vì vậy bạn có thể nhận được một con trỏ tới "một trong quá khứ kết thúc" của đối tượng đơn lẻ. Do đó, p0 + 1
hợp lệ.
không hợp lệ là truy cập đối tượng được lưu trữ tại địa chỉ đó mặc dù con trỏ thu được qua p0 + 1
. Tức là, p0[1].i
là hành vi không xác định. Đây chỉ là UB trước khi rửa nó như sau.
Bây giờ, chúng ta hãy nhìn vào một khả năng khác nhau:
X x[2];
x[1].~X(); //Destroy this object.
new(x + 1) X; //Construct a new one.
Vì vậy, hãy hỏi một số câu hỏi:
là x[1]
UB? Tôi sẽ nói ... không, nó không phải UB. Tại sao? Bởi vì x[1]
không phải là:
một con trỏ chỉ ra rằng những đối tượng ban đầu, một tài liệu tham khảo mà gọi các đối tượng ban đầu, hoặc tên của đối tượng gốc
x
điểm đến mảng và là người đầu tiên phần tử của mảng đó, không phải phần tử thứ hai. Do đó, nó không trỏ đến đối tượng gốc. Nó không phải là một tham chiếu, cũng không phải là tên của đối tượng đó.
Do đó, nó không đủ điều kiện cho các hạn chế được nêu bởi [basic.life]/8. Vì vậy, x[1]
nên trỏ đến đối tượng mới được xây dựng.
Cho rằng, bạn không cần launder
chút nào.
Vì vậy, nếu bạn làm điều này theo cách hợp pháp, thì bạn không cần launder
tại đây.
Không phải là 'khẳng định (p0 [1] == 43);' một biểu thức không hợp lệ? ... Xem xét loại lớp được tạo ra bởi biểu thức con 'p0 [1]' không có toán tử 'quá tải == (X, int)' – WhiZTiM
@WhiZTiM Lỗi đánh máy rõ ràng là hiển nhiên? – Barry
Đó là một lỗi đánh máy. – Oliv