Thuộc tính của một con trỏ đến một mảng có độ dài bằng không


21

Xem xét

int main()
{
    auto a = new int[0];
    delete[] a; // So there's no memory leak
}

Giữa việc khởi tạo và xóa bản sao, bạn có được phép đọc con trỏ tại a + 1không?

Hơn nữa, ngôn ngữ có cho phép trình biên dịch được đặt athành nullptrkhông?


2
@Fareanor: Bạn có thể đọc achắc chắn (bạn chắc chắn không thể bỏ qua nó).
Bathsheba

8
@RasmiRanjanNayak: Đó là hogwash.
Bathsheba

2
@RasmiRanjanNayak Ôi ... không
Ted Lyngmo

1
@TedLyngmo: Khi tôi nói "đọc con trỏ tại a + 1", đoạn mã sau có phải là auto b = a + 1;hành vi không xác định không? (Tôi nghĩ rằng nó là).
Bathsheba

2
@Ayxan Tôi đoán trong trường hợp 0thực sự là kết quả của một số biểu thức mà bạn sẽ không biết cho đến khi chạy. Vì new int[0]an toàn, nó có thể giúp bạn bớt lo lắng về một số trường hợp phân nhánh / đặc biệt. Hãy tưởng tượng nếu tôi là để khởi tạo một std::vectorvới std::vector<int> v(0);.
scohe001

Câu trả lời:


3
    auto a = new int[0];

Theo [basic.compound.3] , giá trị được lưu trữ aphải là một trong những điều sau đây:

  1. Một con trỏ tới một đối tượng (có kiểu int)
  2. Một con trỏ đi qua phần cuối của một đối tượng
  3. Vô giá trị
  4. không hợp lệ

Chúng ta có thể loại trừ khả năng đầu tiên vì không có đối tượng thuộc loại được intxây dựng. Khả năng thứ ba được loại trừ vì C ++ yêu cầu trả về một con trỏ không null (xem [basic.stc.dynamic.allocation.2] ). Do đó, chúng ta chỉ còn hai khả năng: một con trỏ đi qua phần cuối của một đối tượng hoặc một con trỏ không hợp lệ.

Tôi sẽ có khuynh hướng xem anhư một con trỏ quá khứ, nhưng tôi không có một tài liệu tham khảo có uy tín để xác định rõ ràng điều đó. (Tuy nhiên, có một hàm ý mạnh mẽ của điều này trong [basic.stc] , xem làm thế nào bạn có thể deletecon trỏ này.) Vì vậy, tôi sẽ giải trí cả hai khả năng trong câu trả lời này.

Giữa việc khởi tạo và xóa bản sao, bạn có được phép đọc con trỏ tại a + 1không?

Hành vi không được xác định, như được chỉ định bởi [expr.add.4] , bất kể khả năng nào từ phía trên áp dụng.

Nếu alà một con trỏ quá khứ, thì nó được coi là trỏ đến phần tử giả định tại chỉ mục 0của một mảng không có phần tử. Thêm số nguyên jvào achỉ được xác định khi 0≤0+j≤n, nkích thước của mảng. Trong trường hợp của chúng tôi, nbằng không, vì vậy tổng a+jchỉ được xác định khi j0. Cụ thể, việc thêm 1là không xác định.

Nếu akhông hợp lệ, thì chúng tôi hoàn toàn rơi vào "Nếu không, hành vi không được xác định." (Không ngạc nhiên, các trường hợp được xác định chỉ bao gồm các giá trị con trỏ hợp lệ.)

Hơn nữa, ngôn ngữ có cho phép trình biên dịch được đặt athành nullptrkhông?

Không. Từ [basic.stc.dynamic.allocation.2] đã đề cập ở trên : "Nếu yêu cầu thành công, giá trị được trả về bởi hàm phân bổ có thể thay thế là giá trị con trỏ không null" . Ngoài ra còn có một chú thích gọi ra rằng C ++ (nhưng không phải C) yêu cầu một con trỏ không null để đáp ứng yêu cầu bằng không.


1
Nếu đó là một giá trị con trỏ không hợp lệ, bạn sẽ gặp vấn đề nghiêm trọng từ eel.is/c++draft/basic.stc#4
TC

@TC Đúng, điều đó ngụ ý mạnh mẽ rằng nó không thể là một giá trị con trỏ không hợp lệ.
JaMiT

23

Mỗi cuộc thảo luận về phản xạ CWG gần đây là kết quả của vấn đề biên tập 3178 , new int[0]tạo ra giá trị con trỏ hiện tại được gọi là giá trị con trỏ "quá khứ" .

Nó theo sau akhông thể là null và a + 1không được xác định bởi [expr.add] / 4 .


4
"Mỗi cuộc thảo luận về phản xạ CWG gần đây là kết quả của vấn đề biên tập 3178, new int[0]tạo ra cái được gọi là" giá trị con trỏ quá khứ "" Điều này không chính xác. Không có nhiều thảo luận. Một người đề xuất rằng giá trị phải là "con trỏ đi qua phần cuối của một đối tượng" và câu lệnh này đã được đặt câu hỏi vì trong trường hợp một mảng có 0các phần tử, không có đối tượng nào ở cuối phần cuối.
Luật sư ngôn ngữ

@L LanguageLawyer dường như không có nghi ngờ gì a + 1là không xác định trong mọi trường hợp, vì vậy quan điểm của bạn chỉ liên quan đến việc acó thể là null?
MM

Dường như không có bất kỳ sự bất đồng nào về ngữ nghĩa dự định, cũng như tên hiện tại của loại giá trị con trỏ này không phù hợp với kịch bản này.
TC

@MM Tôi nghĩ rằng điều đó a + 1là không xác định và có thể giá trị con trỏ kết quả sẽ được gọi là "con trỏ qua cuối". Tôi không nói rằng câu trả lời là sai. Điều này hơi không chính xác bởi vì có thể hiểu rằng có một cuộc thảo luận kéo dài với sự đồng thuận chỉ xác định rằng kết quả là "con trỏ đi đến cuối" là đủ để giải quyết vấn đề. Vấn đề với "con trỏ qua điểm cuối" là nó đã qua phần cuối của một số đối tượng và trừ đi 1một giá trị con trỏ như vậy sẽ tạo ra một con trỏ cho đối tượng, có lẽ không nên là trường hợp cho các mảng của 0các phần tử.
Luật sư ngôn ngữ

2
@Bathsheba Bạn có nghĩ rằng có thể có bất cứ điều gì có thẩm quyền hơn về từ ngữ khiếm khuyết?
Luật sư ngôn ngữ
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.