Tôi có thể sử dụng gì thay vì toán tử mũi tên, `->`?


112

Toán tử mũi tên ( ->) đồng nghĩa với điều gì?

Câu trả lời:


148

Hai biểu thức sau là tương đương:

a->b

(*a).b

(tùy thuộc vào quá tải toán tử, như Konrad đề cập, nhưng điều đó là bất thường).


9
Các vấn đề quá tải ít bất thường hơn bạn nghĩ. Cách đây không lâu, các trình triển khai STL không có ->toán tử nạp chồng cho một số kiểu trình vòng lặp nên bạn phải sử dụng *.. Nhiều thư viện định nghĩa chúng không nhất quán. Thực sự trở nên khó chịu khi bạn làm việc với các mẫu và không biết loại chính xác.
Konrad Rudolph

1
bạn cũng có thể làm a[0].bthay vì (*a).b. Nhưng nó sẽ không được cấu trúc đúng như vậy.
Sellorio

2
Cậu bé, sau nhiều năm lập trình c #, việc quay trở lại với c ++ không chỉ là đánh thuế về mặt nhận thức, cú pháp c ++ vừa xấu xí vừa kém cỏi. Tôi cảm thấy như đang tắm sau khi sử dụng nó. Các chương trình được viết bằng c và c ++ chỉ khuyến khích lập trình tồi. Apple, pre-unix, đã phải vật lộn để làm cho ngôn ngữ đẹp như Pascal.
ATL_DEV

@ATL_DEV Tôi muốn tranh luận rằng rất nhiều thứ xấu xí không còn được coi là thành ngữ nữa, nhưng tiếc là điều đó không có nghĩa là bạn có đủ khả năng để không quen thuộc với nó như một lập trình viên C ++ thực hành. Ngoài ra, con đường tốt đẹp về mặt cú pháp thường không phải là con đường tốt đẹp về mặt ngữ nghĩa, nhưng nó cũng đã trở nên tốt hơn chứ không phải tệ hơn. Nhưng sau đó tôi lại mắc phải Hội chứng Stockholm C ++.
Tim Seguine

@TimSeguine Nếu bạn muốn xem những đoạn mã đẹp, hãy xem tài liệu hướng dẫn bên trong Macintosh. Tôi nghĩ họ đã phát minh ra CamelCase. Tên biến rất mô tả và mã được định dạng trang nhã. Họ đã cố gắng làm cho mã C sau này của họ gần như tuyệt đẹp như mã Pascal trước đó của họ.
ATL_DEV

70

a->bnói chung là một từ đồng nghĩa với (*a).b. Các dấu ngoặc đơn ở đây là cần thiết vì độ bền liên kết của các toán tử *.: *a.bsẽ không hoạt động vì .liên kết mạnh hơn và được thực thi trước. Do đó, điều này tương đương với *(a.b).

Tuy nhiên, hãy cẩn thận với quá tải: Vì cả hai ->*có thể bị quá tải, ý nghĩa của chúng có thể khác nhau đáng kể.


1
Theo binding strengthbạn nghĩa là ưu tiên toán tử? nếu không sự khác biệt giữa hai là gì?
vishnuprasanth

1
@Vizkrig Có, hai thuật ngữ được sử dụng thay thế cho nhau (mặc dù “ưu tiên toán tử” dường như thường xuyên hơn nhiều, ít nhất là trong những năm gần đây).
Konrad Rudolph

45

Ngôn ngữ C ++ định nghĩa toán tử mũi tên ( ->) là một từ đồng nghĩa để tham chiếu đến một con trỏ và sau đó sử dụng .-operator trên địa chỉ đó.

Ví dụ:

Nếu bạn có một một đối tượng, anObjectvà một con trỏ, aPointer:

SomeClass anObject = new SomeClass();
SomeClass *aPointer = &anObject;

Để có thể sử dụng một trong các phương thức đối tượng, bạn bỏ qua con trỏ và thực hiện một lệnh gọi phương thức trên địa chỉ đó:

(*aPointer).method();

Có thể viết bằng toán tử mũi tên:

aPointer->method();

Lý do chính của sự tồn tại của toán tử mũi tên là nó làm ngắn việc nhập một tác vụ rất phổ biến và nó cũng dễ quên dấu ngoặc đơn xung quanh hội nghị của con trỏ. Nếu bạn quên dấu ngoặc đơn, toán tử.-Sẽ liên kết mạnh hơn sau đó là * -operator và làm cho ví dụ của chúng ta thực thi như sau:

*(aPointer.method()); // Not our intention!

Một số câu trả lời khác cũng đã đề cập đến cả hai toán tử C ++ có thể bị quá tải và nó không phổ biến.


8
new SomeClass()trả về một con trỏ ( SomeClass *), không phải SomeClassđối tượng. Và bạn bắt đầu với việc khai báo anObjectaPointernhưng bạn đang sử dụng psau đó.
musiphil

Nhìn chung, lời giải thích này về mặt lý thuyết là rất phù hợp, chỉ có sự thay đổi của các đối tượng làm cho nó hơi phức tạp. Nhưng quá trình này được mô tả tốt hơn
Code Man

17

Trong C ++ 0x, toán tử có nghĩa thứ hai, cho biết kiểu trả về của một hàm hoặc biểu thức lambda

auto f() -> int; // "->" means "returns ..."

1
Về mặt kỹ thuật, nó không còn là "nhà điều hành" ở đó nữa, hay là nó?
Martin Ba

6
@Martin hầu hết mọi người sử dụng từ "toán tử" cho nhiều thứ không được sử dụng trực tiếp cho các giá trị tính toán. Giống như cho "::" ("toán tử phạm vi"). Tôi không biết chính xác quan điểm của tiêu chuẩn về vấn đề này là gì. Theo nghĩa trừu tượng, người ta có thể xem "->" như một toán tử hàm ánh xạ một chuỗi các kiểu (tham số) thành một kiểu trả về, giống như toán tử haskell, được viết "->".
Johannes Schaub - litb

6
Tôi đầu hàng! :-P
Martin Ba

2
@ JohannesSchaub-litb: ::thực sự là một toán tử, giống như .hoặc ->, và được gọi là "toán tử phân giải phạm vi" trong tiêu chuẩn.
musiphil 7/12/12

13

Tôi chủ yếu đọc nó từ phải sang trái và gọi "in"

foo->bar->baz = qux->croak

trở thành:

"baz in bar trong foo trở thành croak in qux."


1

-> được sử dụng khi truy cập dữ liệu mà bạn có con trỏ tới.

Ví dụ: bạn có thể tạo một con trỏ ptr tới biến kiểu int intVar như sau:

int* prt = &intVar;

Sau đó, bạn có thể sử dụng một hàm, chẳng hạn như foo, trên nó chỉ bằng cách tham chiếu đến con trỏ đó - để gọi hàm trên biến mà con trỏ trỏ đến, thay vì giá trị số của vị trí bộ nhớ của biến đó:

(*ptr).foo();

Nếu không có dấu ngoặc ở đây, trình biên dịch sẽ hiểu điều này là *(ptr.foo())do sự ưu tiên của toán tử không phải là điều chúng ta muốn.

Điều này thực sự cũng giống như gõ

ptr->foo();

Như là các ->tham chiếu mà con trỏ, và do đó gọi hàm foo()trên biến mà con trỏ đang trỏ tới cho chúng ta.

Tương tự, chúng ta có thể sử dụng ->để truy cập hoặc đặt thành viên của một lớp:

myClass* ptr = &myClassMember;
ptr->myClassVar = 2; 

0

Bạn có thể sử dụng -> để xác định một hàm.

auto fun() -> int
{
return 100;
}

Nó không phải là lambda. Nó thực sự là một chức năng. "->" cho biết kiểu trả về của hàm.

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.