2014-11-27 14 views
7

Từ những gì tôi biết, tham chiếu chỉ là một tên khác cho một biến trong khi con trỏ là biến riêng của chúng. Con trỏ chiếm không gian. Mọi người thường nói "sử dụng một tham chiếu hoặc con trỏ" nhưng họ không nói cái nào tốt hơn. Nếu tham chiếu không chiếm được bộ nhớ của riêng chúng, thì tài liệu tham khảo sẽ giành chiến thắng trong bộ phận đó. Những gì tôi không biết là nếu trình biên dịch làm cho một sự khác biệt giữa tài liệu tham khảo và biến bình thường. Nếu bạn thực hiện các phép toán trên một tham chiếu, nó có biên dịch tới cùng một mã như biến thông thường không?Tham chiếu hoặc con trỏ có nhanh hơn không?

+1

W.r.t. hiệu suất, có lẽ không nhiều (chạy một số phép đo để kiểm tra trên nền tảng của bạn). Tôi nghĩ rằng nó là quan trọng hơn để làm rõ các ngữ nghĩa bạn muốn - ghi nhớ, con trỏ có thể là NULL, do đó có thể được lập luận là tùy chọn. – Niall

+3

Tài liệu tham khảo là con trỏ trong ngụy trang, lợi thế hiệu suất duy nhất có thể đến từ một số giả định bổ sung trình biên dịch có thể làm cho chúng (chúng không thể được reseated một cách hợp pháp, cũng không thể NULL). –

+0

Ngược lại, người dùng có thể quá sợ để vượt qua con trỏ NULL ngay cả khi tham số con trỏ được thiết kế là tùy chọn. –

Trả lời

3

Tham chiếu nội bộ cũng được triển khai theo dạng con trỏ. Vì vậy, rất khó để nói đó là con trỏ/tham khảo nhanh hơn.

Đó là cách sử dụng hai yếu tố này tạo sự khác biệt.

Ví dụ: bạn muốn chuyển bằng tham chiếu tham số đến hàm.

void func(int& a) case_1 
{ 
    //No need to check for NULL reference... 
} 
void func(int* a) case_2 
{ 
    //Need o check if pointer is not NULL 
} 

Trong case_2 bạn phải kiểm tra một cách rõ ràng nếu con trỏ không phải là NULL trước khi dereferncing nó trong khi đó không phải là trường hợp với tài liệu tham khảo vì tài liệu tham khảo được khởi tạo một cái gì đó.

Assumption là bạn đang chơi trò chơi trong nếp sống văn minh tức là

Bạn chưa làm điều gì đó như: -

int*p = NULL; 
int &a = *p; 
+0

Phần đầu tiên hoàn toàn đúng. Tuy nhiên, trong thực tế, nhiều kiểm tra NULL là không cần thiết. Chỉ cần tài liệu trong các bình luận chức năng mà bạn mong đợi một con trỏ không NULL và để cho các trang null sụp đổ chương trình nếu điều kiện tiên quyết đó không được đáp ứng. – cmaster

+0

Trong thực tế, bạn nhận được nhiều lỗi phân đoạn do truy cập con trỏ xấu. – ravi

+1

Trong thực tế, bạn có thể nhận được nhiều segfaults do truy cập tham khảo xấu ... – cmaster

1

Họ đều giống nhau, tài liệu tham khảo chỉ là một thợ sửa ngôn ngữ mà là một con trỏ mà không thể rỗng. Sự khác biệt vẫn chỉ trong giai đoạn biên dịch, nơi bạn sẽ nhận được đơn khiếu nại nếu bạn cố gắng làm điều gì đó bất hợp pháp.

+0

Chúng có thể là NULL trong thực tế, mặc dù tiêu chuẩn ngôn ngữ gọi hành vi không xác định khi tạo tham chiếu NULL. Hiệu ứng cũng giống như với con trỏ NULL. Chỉ khó khăn hơn để gỡ lỗi, vì nhiều người sẽ được lao động theo ảo tưởng rằng tài liệu tham khảo không thể là NULL, và do đó không hiểu những gì đang xảy ra trong mã của họ. – cmaster

+0

Có thể, nhưng mã luôn có thể giả định là không. – mukunda

+0

Bạn có thể sử dụng cùng một giả định trên một con trỏ, với cùng một hậu quả. – cmaster

1

Dưới đây là hai chương trình thử nghiệm của tôi:

tham khảo:

int i = 0; 
int& r = i; 
++r; 
int j = 0; 
++j; 

con trỏ:

int i = 0; 
int* r = &i; 
++(*r); 
int j = 0; 
++j; 

trình biên dịch của tôi đã viết mã chính xác cùng một lắp ráp cho cả hai.

movl $0, -16(%rbp) #, i 
leaq -16(%rbp), %rax #, tmp87 
movq %rax, -8(%rbp) # tmp87, r 
movq -8(%rbp), %rax # r, tmp88 
movl (%rax), %eax # *r_1, D.31036 
leal 1(%rax), %edx #, D.31036 
movq -8(%rbp), %rax # r, tmp89 
movl %edx, (%rax) # D.31036, *r_1 
movl $0, -12(%rbp) #, j 
addl $1, -12(%rbp) #, j 
movl $0, %eax #, D.31036 
+0

Bạn có thể kết xuất cụm từ với cờ tối ưu như '-O3' hoặc' -O2' và so sánh lại. –

+0

Kết xuất tốt hơn với '-Os', nó mang lại mã lắp ráp dễ đọc nhất. – cmaster

+0

Tôi không muốn làm điều đó vì nó sẽ tối ưu hóa toàn bộ mã, điều này không hữu ích. – user4298783

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