Con trỏTrong chương trước đó, biến đã được giải thích như các vị trí trong bộ nhớ của máy tính mà có thể được truy cập bằng mã định danh của họ (tên của họ). Bằng cách này, chương trình không cần phải quan tâm đến địa chỉ vật lý của các dữ liệu trong bộ nhớ; nó chỉ đơn giản là sử dụng các định danh bất cứ khi nào nó cần phải đề cập đến biến.Đối với một chương trình C++, bộ nhớ của máy tính là giống như một loạt các tế bào bộ nhớ, mỗi một byte Kích thước, và với một địa chỉ duy nhất. Các tế bào bộ nhớ đơn byte được sắp xếp theo một cách mà cho phép dữ liệu đại diện lớn hơn một byte để chiếm tế bào bộ nhớ có liên tiếp địa chỉ.Bằng cách này, mỗi tế bào có thể được dễ dàng đặt trong bộ nhớ bằng phương tiện của địa chỉ duy nhất của nó. Ví dụ, các tế bào bộ nhớ với địa chỉ 1776 luôn luôn sau ngay sau khi các tế bào với địa chỉ năm 1775 đến trước một với năm 1777, và là chính xác một ngàn các tế bào sau khi tế bào 776 và chính xác một ngàn trước khi 2776.Khi một biến bùng nổ, bộ nhớ cần thiết để lưu trữ giá trị của nó được phân công một địa điểm cụ thể trong bộ nhớ (địa chỉ bộ nhớ của nó). Nói chung, chương trình C++ không tích cực quyết các địa chỉ bộ nhớ chính xác nơi các biến được lưu trữ. May mắn thay, nhiệm vụ đó là trái với môi trường nơi mà chương trình chạy - nói chung, Hệ điều hành quyết định các vị trí cụ thể bộ nhớ trên thời gian chạy. Tuy nhiên, nó có thể hữu ích cho một chương trình để có thể để có được địa chỉ của một biến trong thời gian chạy để truy cập vào dữ liệu các tế bào đang ở một vị trí nhất định liên quan đến nó.Địa chỉ của nhà điều hành (&)Địa chỉ của một biến có thể được thu được bằng ngay trước tên của một biến với một dấu hiệu dấu "và" (&), được gọi là địa chỉ của nhà điều hành. Ví dụ: foo = & myvar;Điều này sẽ chỉ định địa chỉ của biến myvar cho foo; bởi ngay trước tên của biến myvar với địa chỉ của nhà điều hành (&), chúng tôi không còn cho nội dung của biến riêng của mình để foo, nhưng địa chỉ của nó.Địa chỉ thực tế của một biến trong bộ nhớ không thể được biết đến trước khi thời gian chạy, nhưng hãy giả sử, để giúp làm rõ một số khái niệm, myvar đó được đặt trong thời gian chạy trong địa chỉ bộ nhớ năm 1776.Trong trường hợp này, hãy xem xét các đoạn mã sau đây:123myvar = 25;foo = & myvar;vaïch = myvar;Các giá trị chứa trong mỗi biến sau khi thực hiện điều này được thể hiện trong sơ đồ sau đây: Trước tiên, chúng tôi đã chỉ định giá trị 25 để myvar (một biến có địa chỉ trong bộ nhớ, chúng tôi giả định là 1776).Các báo cáo thứ hai gán foo địa chỉ myvar, chúng tôi đã giả định là năm 1776.Cuối cùng, tuyên bố thứ ba, chỉ định giá trị chứa trong myvar để bar. Đây là một hoạt động tiêu chuẩn phân công, như đã thực hiện nhiều lần trong chương trước đó.Sự khác biệt chính giữa những điều khoản về thứ hai và thứ ba là sự xuất hiện của các địa chỉ của nhà điều hành (&).Biến mà các cửa hàng địa chỉ của một biến (như foo trong ví dụ trước) là những gì trong C++ được gọi là một con trỏ. Con trỏ là một tính năng rất mạnh mẽ của ngôn ngữ mà có nhiều công dụng trong chương trình cấp thấp hơn. Một chút sau đó, chúng tôi sẽ xem làm thế nào để tuyên bố và sử dụng con trỏ.Trỏ nhà điều hành (*)Như đã chỉ thấy, một biến mà các cửa hàng địa chỉ của một biến được gọi là một con trỏ. Con trỏ được cho là "điểm đến" thay đổi địa chỉ mà họ lưu trữ.Một bất động sản thú vị của con trỏ là họ có thể được sử dụng để truy cập vào các biến họ chỉ trực tiếp. Điều này được thực hiện bởi ngay trước tên con trỏ với các nhà điều hành dereference (*). Các nhà điều hành chính nó có thể được đọc như "giá trị được chỉ tới bởi".Vì vậy, sau đây với giá trị của các ví dụ trước đó, các tuyên bố sau: Baz = * foo;Điều này có thể được đọc như: "baz bằng giá trị chỉ tới bởi foo", và tuyên bố sẽ thực sự chỉ định giá trị 25 cho baz, kể từ khi foo là năm 1776, và giá trị được chỉ tới bởi 1776 (sau ví dụ ở trên) sẽ là 25. Nó là quan trọng để phân biệt rõ ràng mà foo đề cập đến giá trị năm 1776, trong khi * foo (với dấu hoa thị * ngay trước các định danh) đề cập đến các giá trị được lưu trữ tại địa chỉ năm 1776, mà trong trường hợp này là 25. Nhận thấy sự khác biệt của bao gồm hoặc không bao gồm các nhà điều hành dereference (tôi đã thêm một bình luận giải thích như thế nào mỗi hai biểu thức có thể được đọc): 12Baz = foo; Baz bằng foo (1776)Baz = * foo; Baz bằng giá trị được chỉ tới bởi foo (25) Tham khảo và trỏ nhà khai thác được như vậy, bổ sung:& là địa chỉ của nhà điều hành, và có thể được đọc đơn giản là "địa chỉ"* đang sử dụng dereference nhiều, và có thể được đọc như "giá trị được chỉ tới bởi"Vì vậy, họ có ý nghĩa đối diện loại: địa chỉ thu được với & có thể được dereferenced với *.Trước đó, chúng tôi thực hiện các hoạt động hai nhiệm vụ sau đây:12myvar = 25;foo = & myvar;Ngay sau khi các báo cáo hai, tất cả những biểu hiện sau sẽ cung cấp cho đúng như là kết quả:1234myvar == 25& myvar == năm 1776foo == năm 1776* foo == 25Các biểu hiện đầu tiên là khá rõ ràng, xem xét rằng các hoạt động chuyển nhượng thực hiện trên myvar là myvar = 25. Thứ hai sử dụng các địa chỉ của nhà điều hành (&), mà trả về địa chỉ myvar, mà chúng tôi cho rằng nó có giá trị năm 1776. Thứ 3 là phần nào rõ ràng, kể từ thứ hai biểu thức là đúng sự thật và đã là phân công hoạt động thực hiện trên foo foo = & myvar. Sử dụng biểu thức thứ tư các nhà điều hành dereference (*) mà có thể được đọc như là "giá trị được chỉ tới bởi", và giá trị được chỉ tới bởi foo thực sự là 25.Vì vậy, sau khi tất cả, bạn có thể cũng suy ra rằng đối với miễn là địa chỉ chỉ tới bởi foo vẫn không thay đổi, những biểu hiện sau đây sẽ cũng là đúng: * foo == myvarTuyên bố con trỏDue to the ability of a pointer to directly refer to the value that it points to, a pointer has different properties when it points to a char than when it points to an int or a float. Once dereferenced, the type needs to be known. And for that, the declaration of a pointer needs to include the data type the pointer is going to point to.The declaration of pointers follows this syntax:type * name; where type is the data type pointed to by the pointer. This type is not the type of the pointer itself, but the type of the data the pointer points to. For example:123int * number;char * character;double * decimals;These are three declarations of pointers. Each one is intended to point to a different data type, but, in fact, all of them are pointers and all of them are likely going to occupy the same amount of space in memory (the size in memory of a pointer depends on the platform where the program runs). Nevertheless, the data to which they point to do not occupy the same amount of space nor are of the same type: the first one points to an int, the second one to a char, and the last one to a double. Therefore, although these three example variables are all of them pointers, they actually have different types: int*, char*, and double* respectively, depending on the type they point to.Note that the asterisk (*) used when declaring a pointer only means that it is a pointer (it is part of its type compound specifier), and should not be confused with the dereference operator seen a bit earlier, but which is also written with an asterisk (*). They are simply two different things represented with the same sign.Let's see an example on pointers:1234567891011121314151617// my first pointer#include using namespace std;int main (){ int firstvalue, secondvalue; int * mypointer; mypointer = &firstvalue; *mypointer = 10; mypointer = &secondvalue; *mypointer = 20; cout << "firstvalue is " << firstvalue << '
'; cout << "secondvalue is " << secondvalue << '
'; return 0;}firstvalue is 10secondvalue is 20Edit & RunNotice that even though neither firstvalue nor secondvalue are directly set any value in the program, both end up with a value set indirectly through the use of mypointer. This is how it happens:First, mypointer is assigned the address of firstvalue using the address-of operator (&). Then, the value pointed to by mypointer is assigned a value of 10. Because, at this moment, mypointer is pointing to the memory location of firstvalue, this in fact modifies the value of firstvalue.In order to demonstrate that a pointer may point to different variables during its lifetime in a program, the example repeats the process with secondvalue and that same pointer, mypointer.
Here is an example a little bit more elaborated:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// more pointers
#include
using namespace std;
int main ()
{
int firstvalue = 5, secondvalue = 15;
int * p1, * p2;
p1 = &firstvalue; // p1 = address of firstvalue
p2 = &secondvalue; // p2 = address of secondvalue
*p1 = 10; // value pointed to by p1 = 10
*p2 = *p1; // value pointed to by p2 = value pointed to by p1
p1 = p2; // p1 = p2 (value of pointer is copied)
*p1 = 20; // value pointed to by p1 = 20
cout << "firstvalue is " << firstvalue << '
';
cout << "secondvalue is " << secondvalue << '
';
return 0;
}
firstvalue is 10
secondvalue is 20
Edit & Run
Each assignment operation includes a comment on how each line could be read: i.e., replacing ampersands (&) by "address of", and asterisks (*) by "value pointed to by".
Notice that there are expressions with pointers p1 and p2, both with and without the dereference operator (*). The meaning of an expression using the dereference operator (*) is very different from one that does not. When this operator precedes the pointer name, the expression refers to the value being pointed, while when a pointer name appears without this operator, it refers to the value of the pointer itself (i.e., the address of what the pointer is pointing to).
Another thing that may call your attention is the line:
int * p1, * p2;
This declares the two pointers used in the previous example. But notice that there is an asterisk (*) for each pointer, in order for both to have
đang được dịch, vui lòng đợi..
