2011-12-18 34 views
5

Theo quy tắc nghiêm ngặt răng cưa:char * chuyển đổi và răng cưa quy tắc

struct B { virtual ~B() {} }; 
struct D : public B { }; 

D d; 
char *c = reinterpret_cast<char*>(&d); 

Một char* cho bất kỳ đối tượng kiểu khác nhau là hợp lệ. Nhưng bây giờ câu hỏi là, nó sẽ trỏ đến cùng một địa chỉ của & d? những gì là đảm bảo được thực hiện bởi C + + Standard rằng nó sẽ trả về cùng một địa chỉ?

+9

Tôi nghĩ rằng hàm hủy của bạn bị đặt tên sai –

+4

Tôi không biết câu trả lời. Nhưng, khi nào thì kiến ​​thức này ** bao giờ ** có ích trong thực tế? –

+0

Câu hỏi hay. Một số phôi thực sự có thể thay đổi địa chỉ (ví dụ: khi có nhiều lần thừa kế).Tôi tự hỏi nếu đó là trường hợp. – Kos

Trả lời

6

c&d thực sự có cùng giá trị và nếu bạn diễn giải lại c quay lại D* bạn sẽ nhận được con trỏ hợp lệ mà bạn có thể coi trọng. Hơn nữa, bạn có thể xử lý c như (con trỏ đến phần tử đầu tiên) một mảng mờ char[sizeof(D)] - đây thực sự là mục đích chính của việc đưa con trỏ đến con trỏ char: Để cho phép (de) tuần tự hóa (ví dụ: ofile.write(c, sizeof(D));), mặc dù bạn thường chỉ làm điều này cho các kiểu nguyên thủy (và các mảng của chúng), vì bố cục nhị phân của các loại hợp chất thường không được xác định theo kiểu di động.

Khi @Oli đúng chỉ ra và muốn tôi củng cố, bạn thực sự không bao giờ nên sắp xếp từng loại hợp chất nói chung. Kết quả sẽ hầu như không bao giờ được deserializable, kể từ khi thực hiện các lớp đa hình và đệm giữa các lĩnh vực dữ liệu không được chỉ định và không thể truy cập cho bạn.

Lưu ý rằng reinterpret_cast<char*>(static_cast<B*>(&d)) có thể được coi là mảng mờ char[sizeof(B)] do lý do tương tự.

+0

Tôi nghĩ có lẽ bạn nên làm cho nó rõ ràng hơn rằng serializing/deserializing các lớp không POD như thế này (tức là những người có vptrs) là một ý tưởng rất rất xấu. –

+0

@OliCharlesworth: Hm, các * đối tượng * không có bất kỳ "vptrs" ẩn nào ... tất cả chỉ là trong quá trình triển khai lớp. Các đối tượng vẫn nên có bố trí khá "bình thường", ít nhất là cho đến khi bạn vào được thừa kế ảo ... vấn đề đệm thông thường là một lý do ngay lập tức hơn không phải để sắp xếp các loại lớp theo cách "ngây thơ" (mặc dù sau đó lại có thể có các tình huống trong đó OK, ví dụ: cụm HPC của các máy giống nhau sử dụng I/O mạng được ánh xạ bộ nhớ ...). Người mua hãy cẩn thận :-) –

+0

Cái gì? Sự tồn tại của các hàm ảo có nghĩa là các cá thể lớp phải có một vptr (tốt, trong bất kỳ việc triển khai điển hình nào). –

2

Mục 5.2.10, điểm 7 của C++ Standard 2003 nói:

Một con trỏ đến một đối tượng có thể được chuyển đổi một cách rõ ràng để một con trỏ đến một đối tượng kiểu khác nhau. Ngoại trừ việc chuyển đổi giá trị của loại "con trỏ thành T1" thành loại "con trỏ thành T2" (trong đó T1 và T2 là loại đối tượng và yêu cầu căn chỉnh của T2 không có số chặt hơn so với T1) và quay lại loại ban đầu của nó mang lại giá trị con trỏ gốc, kết quả của việc chuyển đổi con trỏ như vậy là không xác định.

Nếu theo "cùng một địa chỉ", bạn có nghĩa là "giá trị con trỏ ban đầu", thì mục này cho biết "có".

0

Mục đích rõ ràng (và không phải cái gì mà cần phải được thảo luận):

reinterpret_cast bao giờ thay đổi giá trị của một địa chỉ, trừ các loại mục tiêu không thể đại diện tất cả các giá trị địa chỉ (như một kiểu số nguyên nhỏ, trên một kiểu con trỏ với sự căn chỉnh nội tại: f.ex. một con trỏ chỉ có thể biểu diễn các địa chỉ, hoặc con trỏ tới đối tượng và con trỏ tới các hàm không thể được trộn lẫn ...).

Từ ngữ của tiêu chuẩn không thể ghi lại điều đó, nhưng điều đó không có nghĩa là có một vấn đề thực tế thực sự ở đây.

char *c = reinterpret_cast<char*>(&d); 

c sẽ trỏ đến byte đầu tiên d, luôn.

Các vấn đề liên quan