Số học con trỏ trên bộ nhớ được phân bổ có được phép kể từ C ++ 20 không?


10

Trong tiêu chuẩn C ++ 20, người ta nói rằng các kiểu mảng là kiểu trọn đời ẩn .

Điều đó có nghĩa là một mảng cho một kiểu trọn đời không ngầm có thể được tạo ngầm? Việc tạo ngầm định một mảng như vậy sẽ không gây ra việc tạo các phần tử của mảng?

Hãy xem xét trường hợp này:

//implicit creation of an array of std::string 
//but not the std::string elements:
void * ptr = operator new(sizeof (std::string) * 10);
//use launder to get a "pointer to object" (which object?)
std::string * sptr = std::launder(static_cast<std::string*>(ptr));
//pointer arithmetic on not created array elements well defined?
new (sptr+1) std::string("second element");

Mã này không phải là UB nữa kể từ C ++ 20?


Có lẽ cách này là tốt hơn?

//implicit creation of an array of std::string 
//but not the std::string elements:
void * ptr = operator new(sizeof (std::string) * 10);
//use launder to get a "pointer to the array of 10 std::string" 
std::string (* sptr)[10] = std::launder(static_cast<std::string(*)[10]>(ptr));
//pointer arithmetic on an array is well defined
new (*sptr+1) std::string("second element");

1
Tôi vừa thực hiện tìm kiếm thông qua tiêu chuẩn (bản nháp) C ++ 20 và không tìm thấy gì mô tả các mảng là "loại vòng đời ngầm" (và, vâng, tôi đã tìm kiếm các biến thể). Vui lòng cung cấp mô tả chi tiết hơn về khiếu nại của bạn (ví dụ: phần và điều khoản trong tiêu chuẩn). Hơi khó để trả lời câu hỏi của bạn mà không thể tìm thấy nguồn, nói gì đến bất kỳ bối cảnh liên quan nào.
Peter

1
@Peter : eel.is/c++draft/basic.types#9 , câu cuối cùng
geza

Tôi đã xem PDF open-std.org/jtc1/sc22/wg21/docs/ con / 2020 / n4849.pdf (rõ ràng là bản thảo làm việc mới nhất) và nó thậm chí không có câu đó. Có vẻ như bạn cũng sẽ cần tìm ý nghĩa của "cuộc sống ngầm". Tôi nghi ngờ liên kết của bạn có thể đã nhận được một số "chỉnh sửa đang diễn ra" mà thậm chí còn không đưa nó vào bản nháp đang hoạt động.
Peter

1
@Peter Những thay đổi là kết quả của việc P0593 được sáp nhập vào tiêu chuẩn từ cuộc họp ở Prague gần đây. Họ chưa phát hành bản dự thảo kết quả, nhưng bạn có thể thấy từ ngữ được hợp nhất trong cam kết này .
quả óc chó

Câu trả lời:


3

Liệu nó có nghĩa là một mảng cho một loại trọn đời không ngầm có thể được tạo ra ngầm?

Đúng.

Việc tạo ngầm định một mảng như vậy sẽ không gây ra việc tạo các phần tử của mảng?

Đúng.

Đây là những gì làm cho có thể std::vectorthực hiện được trong C ++ thông thường.


Bạn có thể xác nhận rằng std::launder(static_cast<std::string*>(ptr))nó không trả về một con trỏ cho phần tử đầu tiên của mảng bởi vì nó không nằm trong vòng đời của nó, nhưng nó std::launder(static_cast<std::string(*)[10]>(ptr))trả về một con trỏ cho mảng, bởi vì mảng nằm trong vòng đời của nó?
Oliv

Điều đó có vẻ đúng với tôi.
TC

@Oliv Và tôi cho rằng điều đó std::launderkhông thực sự cần thiết, bởi vì eel.is/c++draft/intro.object#11 đảm bảo rằng nó ptrsẽ trỏ đến mảng?
quả óc chó

@walnut, tôi đã bỏ lỡ điều đó. Vì vậy, một static_castđể std::string (*) [10]nên là đủ! tx.
Oliv

@Oliv Nhưng tôi đoán câu hỏi sau đó trở thành liệu ví dụ đầu tiên của bạn mà không có std::laundersẽ được xác định rõ hay không. Không có std::stringđối tượng để trỏ đến, nhưng ptrcó thể trỏ đến mảng, do đó, việc truyền tĩnh sẽ giữ giá trị không thay đổi và sptrcũng sẽ trỏ đến mảng. Với std::laundernó là UB đơn giản chỉ vì std::launderyêu cầu của.
quả óc chó
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.