Tôi nên sử dụng static_cast hoặc reinterpret_cast khi truyền khoảng trống * cho bất cứ điều gì


202

Cả static_cast và reinterpret_cast dường như hoạt động tốt để truyền void * sang loại con trỏ khác. Có một lý do tốt để ủng hộ cái này hơn cái kia?


78
@anon Rõ ràng bạn chưa bao giờ làm việc với các chủ đề POSIX trước đó.
user470379

7
@ user470379 Wow ... đó là lý do tôi đã đặt ra câu hỏi này tại SO! Quan sát tuyệt vời :-).
Ogre Psalm33

Câu trả lời:


148

Sử dụngstatic_cast : đó là diễn viên hẹp nhất mô tả chính xác những gì chuyển đổi được thực hiện ở đây.

Có một quan niệm sai lầm rằng sử dụng reinterpret_castsẽ là một kết hợp tốt hơn bởi vì điều đó có nghĩa là hoàn toàn bỏ qua loại an toàn và chỉ chuyển từ A sang B.

Tuy nhiên, điều này không thực sự mô tả hiệu quả của a reinterpret_cast. Thay vào đó, reinterpret_castcó một số ý nghĩa, đối với tất cả trong số đó cho rằng bản đồ được thực hiện bởi reinterpret_castđịnh nghĩa được triển khai. [5.2.10.3]

Nhưng trong trường hợp cụ thể của việc đúc từ void*đếnT* ánh xạ thì hoàn toàn được xác định rõ bởi tiêu chuẩn; cụ thể là để gán một loại cho một con trỏ không chữ mà không thay đổi địa chỉ của nó.

Đây là một lý do để thích static_cast.

Ngoài ra, và quan trọng hơn, là thực tế là mọi việc sử dụng reinterpret_castđều hết sức nguy hiểm vì nó chuyển đổi bất cứ thứ gì thực sự khác (đối với con trỏ), trong khi static_casthạn chế hơn nhiều, do đó cung cấp mức độ bảo vệ tốt hơn. Điều này đã cứu tôi khỏi các lỗi mà tôi vô tình cố gắng ép một loại con trỏ vào một loại khác.


8

Đây là một câu hỏi khó. Một mặt, Konrad đưa ra một quan điểm tuyệt vời về định nghĩa đặc tả cho reinterpret_cast , mặc dù trong thực tế, nó có thể làm điều tương tự. Mặt khác, nếu bạn truyền giữa các loại con trỏ (chẳng hạn như khá phổ biến khi lập chỉ mục trong bộ nhớ thông qua char * chẳng hạn), static_cast sẽ tạo ra lỗi trình biên dịch và dù sao bạn cũng sẽ buộc phải sử dụng reinterpret_cast .

Trong thực tế, tôi sử dụng reinterpret_cast vì nó mô tả rõ hơn về ý định của hoạt động diễn viên. Bạn chắc chắn có thể tạo một trường hợp cho một toán tử khác chỉ định diễn giải lại con trỏ (chỉ đảm bảo trả lại cùng một địa chỉ), nhưng không có một tiêu chuẩn nào trong tiêu chuẩn.


6
" Toán tử khác nhau để chỉ định diễn giải lại con trỏ (chỉ đảm bảo trả lại cùng một địa chỉ) " Hug? Toán tử đó reinterpret_cast !
tò mò

2
@cantlyguy Không đúng theo tiêu chuẩn. reinterpret_cast KHÔNG đảm bảo rằng cùng một địa chỉ được sử dụng. Chỉ có điều, nếu bạn reinterpret_cast từ loại này sang loại khác và sau đó quay lại , bạn sẽ lấy lại cùng địa chỉ mà bạn đã bắt đầu.
ClydeTheGhost

0

Tôi đề nghị sử dụng các diễn viên yếu nhất có thể luôn luôn.

reinterpret_cast có thể được sử dụng để truyền con trỏ tới float . Dàn diễn viên càng phá vỡ cấu trúc thì càng cần phải chú ý sử dụng nó.

Trong trường hợp char*, tôi sẽ sử dụng dàn diễn viên kiểu c, cho đến khi chúng tôi có một số reinterpret_pointer_cast, vì nó yếu hơn và không có gì khác là đủ.


2
" Reinterpret_cast có thể được sử dụng để chuyển con trỏ lên hình nổi. " Chắc chắn là không!
tò mò

3
Có lẽfloat f = *reinterpret_cast<const float*>(&p);
Ben Voigt

2
@BenVoigt Đó là đúc giữa các con trỏ; một trong số chúng là một con trỏ nổi.
gật đầu

5
@BenVoigt "toàn bộ biểu thức" không phải là một diễn viên. Biểu thức bao gồm một sự bổ nhiệm được áp dụng cho một diễn viên. Bạn tuyên bố rằng có thể bỏ một con trỏ tới float, đó là sai. Biểu thức void **chuyển sang const float *, và sau đó sử dụng một hoạt động bổ nhiệm (KHÔNG phải là diễn viên), để chuyển đổi const float *thành float.
MM

2
@BenVoigt bạn đã cung cấp mã đó để trả lời cho ai đó hỏi "Làm thế nào để tôi đúc ...", và sau đó khi ai đó nói rằng mã đó nằm giữa các con trỏ (mà nó làm), bạn đã nói "Không"
MM

-7

Sở thích cá nhân của tôi dựa trên kiến ​​thức mã như thế này:

void* data = something;
MyClass* foo = reinterpret_cast<MyClass*>(data);
foo->bar();

hoặc là

typedef void* hMyClass; //typedef as a handle or reference
hMyClass = something;
const MyClass& foo = static_cast<MyClass&>(*hMyClass);
foo.bar();

Cả hai đều làm như vậy cuối cùng, nhưng static_cast có vẻ phù hợp hơn trong môi trường ứng dụng trung gian, trong khi diễn giải lại có vẻ giống như một cái gì đó bạn thấy trong thư viện IMHO cấp thấp hơn.

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.