Truyền theo giá trị C++

Có hai phương pháp để truyền dữ liệu vào hàm trong ngôn ngữ C, tôi. e. , gọi theo giá trị và gọi theo tham chiếu

Truyền theo giá trị C++

Hãy hiểu từng cuộc gọi theo giá trị và cuộc gọi theo tham chiếu trong ngôn ngữ c


Gọi theo giá trị trong C

  • Trong phương thức gọi theo giá trị, giá trị của các tham số thực tế được sao chép vào các tham số chính thức. Nói cách khác, chúng ta có thể nói rằng giá trị của biến được sử dụng trong lệnh gọi hàm trong phương thức gọi theo giá trị
  • Trong phương thức gọi theo giá trị, chúng ta không thể thay đổi giá trị của tham số thực bằng tham số hình thức
  • Trong cuộc gọi theo giá trị, bộ nhớ khác nhau được phân bổ cho các tham số thực tế và chính thức do giá trị của tham số thực tế được sao chép vào tham số chính thức
  • Tham số thực tế là đối số được sử dụng trong lệnh gọi hàm trong khi tham số chính thức là đối số được sử dụng trong định nghĩa hàm

Hãy thử hiểu khái niệm gọi theo giá trị trong ngôn ngữ c bằng ví dụ dưới đây

đầu ra

Before function call x=100
Before adding value inside function num=100
After adding value inside function num=200
After function call x=100


Gọi theo giá trị Ví dụ. Hoán đổi giá trị của hai biến

đầu ra

Before swapping the values in main a = 10, b = 20
After swapping values in function a = 20, b = 10
After swapping values in main a = 10, b = 20  

Gọi theo tham chiếu trong C

  • Trong cuộc gọi theo tham chiếu, địa chỉ của biến được chuyển vào lệnh gọi hàm dưới dạng tham số thực
  • Giá trị của các tham số thực có thể được sửa đổi bằng cách thay đổi các tham số hình thức do địa chỉ của các tham số thực được truyền vào
  • Trong cuộc gọi theo tham chiếu, cấp phát bộ nhớ tương tự cho cả tham số chính thức và tham số thực tế. Tất cả các hoạt động trong hàm được thực hiện trên giá trị được lưu trữ tại địa chỉ của các tham số thực tế và giá trị đã sửa đổi được lưu trữ tại cùng một địa chỉ

Xem xét ví dụ sau cho cuộc gọi theo tham chiếu

đầu ra

Before function call x=100
Before adding value inside function num=100
After adding value inside function num=200
After function call x=200

Gọi theo tham chiếu Ví dụ. Hoán đổi giá trị của hai biến

đầu ra

Before swapping the values in main a = 10, b = 20
After swapping values in function a = 20, b = 10
After swapping values in main a = 20, b = 10  


Sự khác biệt giữa cuộc gọi theo giá trị và cuộc gọi theo tham chiếu trong c

Không. Gọi theo giá trị Gọi theo tham chiếu Một bản sao của giá trị được truyền vào hàm Một địa chỉ của giá trị được truyền vào hàm Những thay đổi được thực hiện bên trong hàm chỉ giới hạn trong hàm. Các giá trị của các tham số thực tế không thay đổi bằng cách thay đổi các tham số chính thức. Các thay đổi được thực hiện bên trong chức năng cũng xác thực bên ngoài chức năng. Các giá trị của các tham số thực sự thay đổi bằng cách thay đổi các tham số hình thức. 3Các đối số chính thức và thực tế được tạo ở các vị trí bộ nhớ khác nhau Các đối số chính thức và thực tế được tạo ở cùng một vị trí bộ nhớ

Theo nghĩa chặt chẽ nhất của từ này, mọi thứ trong C đều là giá trị truyền qua. Điều này thường gây nhầm lẫn cho những người mới bắt đầu lập trình C, đặc biệt khi nói đến con trỏ, mảng và cấu trúc. Vì vậy, chúng ta có ý gì khi nói truyền theo giá trị và truyền theo tham chiếu

Khi chúng ta chuyển theo giá trị, chúng ta đang chuyển một bản sao của biến cho một hàm. Khi chúng ta chuyển qua tham chiếu, chúng ta đang chuyển một bí danh của biến cho một hàm. C có thể truyền một con trỏ vào một hàm nhưng đó vẫn là truyền theo giá trị. Nó đang sao chép giá trị của con trỏ, địa chỉ, vào hàm. Trong C++, một tham chiếu là bí danh cho một biến khác. C không có khái niệm này

Trong C khi truyền một con trỏ, cú pháp yêu cầu áp dụng một dereference để lấy giá trị, trong khi ở các ngôn ngữ truyền qua tham chiếu thực sự như Pascal (tham số được khai báo bằng var) và C++ (tham số được khai báo bằng &), yêu cầu đó không . Sẽ đúng hơn nếu gọi cơ chế C là “chuyển tham chiếu”. Hãy xem bài viết wiki này giải thích thêm về Pass by Reference

Hãy xem xét một số mã để làm rõ tất cả những điều này

Truyền nguyên hàm cho các hàm

Hãy xem ví dụ cổ điển về hàm hoán đổi để chuyển nguyên hàm cho hàm

C

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

void hoán đổi(int a, int b);

 

void hoán đổi(int a, int b) {

  int tmp = a;

  a = b;

  b = tmp;

}

 

int chính()

{

    int a = 1;

    int b = 2;

    printf("before swap a = %d\n", a);

    printf("before swap b = %d\n", b);    

    hoán đổi(a, b);

    printf("after swap a = %d\n", a);

    printf("after swap b = %d\n", b);

}

Chạy nó và đầu ra trông như thế này

before swap a = 1
before swap b = 2
after swap a = 1
after swap b = 2

Các giá trị giống nhau được in trước khi hàm hoán đổi được gọi và sau khi nó được gọi. Hàm hoán đổi không ảnh hưởng đến các biến a và b cục bộ của chúng tôi. Tại sao? . Đó là các bản sao được hoán đổi bên trong hàm chứ không phải các biến ban đầu

Bây giờ hãy xem xét một chức năng hơi khác sử dụng con trỏ

C

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

void hoán đổi(int *a, int *b);

 

void hoán đổi(int *a, int *b) {

  int tmp = *a;

  *a = *b;

  *b = tmp;

}

 

int chính()

{

    int a = 1;

    int b = 2;

    printf("before swap a = %d\n", a);

    printf("before swap b = %d\n", b);    

    hoán đổi(&a, &b);

    printf("after swap a = %d\n", a);

    printf("after swap b = %d\n", b);

}

Chạy nó và đầu ra trông như thế này

before swap a = 1
before swap b = 2
after swap a = 2
after swap b = 1

Trong ví dụ này, chúng tôi sử dụng địa chỉ của các biến a và b làm đầu vào cho hàm hoán đổi. Đầu ra cho thấy các giá trị a và b ban đầu đã được hoán đổi thành công. Mặc dù chúng tôi đang sử dụng con trỏ, đây vẫn là giá trị truyền qua. Các bản sao của các con trỏ tới các biến a và b đang được truyền vào hàm. Bản thân hàm thay đổi các giá trị tại các địa chỉ đó nhưng nó vẫn được truyền một bản sao của con trỏ vào hàm, đó là giá trị truyền qua

Truyền cấu trúc cho hàm

Truyền cấu trúc tương tự như truyền nguyên hàm. Nếu một cấu trúc được truyền cho một hàm, các byte của cấu trúc được sao chép dưới dạng tham số của hàm. Bất cứ điều gì được thực hiện với cấu trúc đó trong hàm sẽ thay đổi bản sao, không phải cấu trúc ban đầu

C

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

struct foo {

  int chiều rộng;

  int chiều cao;

};

 

void hoán đổi(struct foo input);

 

void hoán đổi(struct foo input) {

    int tmp = đầu vào.chiều rộng;

    đầu vào. chiều rộng = đầu vào. chiều cao;

    đầu vào. chiều cao = tmp;

}

 

int chính()

{

    struct foo first;

    đầu tiên. chiều rộng = 1;

    đầu tiên. chiều cao = 2;    <

    printf(&quot;before swap first.chiều rộng = %d\ . n&quot;, first.chiều rộng);

    printf(&quot;before swap first.chiều cao = %d\ . n&quot;, first.chiều cao);    

    hoán đổi(đầu tiên);

    printf(&quot;after swap first.chiều rộng = %d\ . n&quot;, first.chiều rộng);

    printf(&quot;after swap first.chiều cao = %d\ . n&quot;, first.chiều cao);

}

Bạn sẽ nhận được đầu ra

before swap first.width = 1
before swap first.height = 2
after swap first.width = 1
after swap first.height = 2

Đầu ra cho thấy thể hiện cấu trúc ban đầu không bị thay đổi. Các byte của thể hiện cấu trúc đã được sao chép vào hàm. Chức năng hoạt động trên bản sao đó. Ví dụ cấu trúc ban đầu không thay đổi

Điều gì xảy ra khi chúng ta sử dụng con trỏ tới cấu trúc?

C

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

struct foo {

  int chiều rộng;

  int chiều cao;

};

 

void hoán đổi(struct foo *input);

 

void hoán đổi(struct foo *input) {

    int tmp = đầu vào-&gt;width;

    đầu vào-&gt;width = input-&gt;height;

    đầu vào-&gt;height = tmp;

}

 

int chính()

{

    struct foo first;

    đầu tiên. chiều rộng = 1;

    đầu tiên. chiều cao = 2;    <

    printf(&quot;before swap first.chiều rộng = %d\ . n&quot;, first.chiều rộng);

    printf(&quot;before swap first.chiều cao = %d\ . n&quot;, first.chiều cao);    

    hoán đổi(&amp;first);

    printf(&quot;after swap first.chiều rộng = %d\ . n&quot;, first.chiều rộng);

    printf(&quot;after swap first.chiều cao = %d\ . n&quot;, first.chiều cao);

}

Bây giờ đầu ra đã khác

before swap first.width = 1
before swap first.height = 2
after swap first.width = 2
after swap first.height = 1

Sử dụng con trỏ, chúng tôi thấy rằng các giá trị trong cấu trúc ban đầu đã được hoán đổi thành công. Tương tự như nguyên thủy, một bản sao của con trỏ đã được chuyển vào hàm. Sau đó, hàm sử dụng con trỏ đó để hoán đổi các giá trị thành viên cấu trúc. Khi sử dụng con trỏ tới cấu trúc, chỉ giá trị con trỏ được sao chép và đây vẫn là giá trị truyền qua

Truyền mảng cho hàm

Khi một mảng được truyền cho một hàm, một con trỏ tới địa chỉ của phần tử đầu tiên của mảng được sao chép vào hàm. Không giống như các cấu trúc, việc truyền một mảng sẽ không sao chép tất cả các byte của mảng vào hàm. Chỉ con trỏ được sao chép

C

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

void hoán đổi(int *nums);

 

void hoán đổi(int *nums) {    

    int tmp = *nums;

    int *tiếp theo = nums + 1;

    *nums = *next;

    *tiếp theo = tmp;

}

 

int chính()

{

    int nums[3] = {1,2};

    printf(&quot;before swap nums[0] = %d\n&quot;, nums[0]);

    printf(&quot;before swap nums[1] = %d\n&quot;, nums[1]);    

    hoán đổi(số);

    printf(&quot;after swap nums[0] = %d\n&quot;, nums[0]);

    printf(&quot;after swap nums[1] = %d\n&quot;, nums[1]);

}

Đầu ra của cái này là

________số 8

Ở đây, chúng tôi khởi tạo một mảng gồm hai int, in ra các giá trị của các chỉ số, chuyển mảng vào hàm hoán đổi và sau đó chúng tôi in lại các giá trị của các chỉ số. Những gì đang được truyền vào hàm hoán đổi là một bản sao của biến mảng, nghĩa là một bản sao địa chỉ của phần tử đầu tiên trong mảng. Sử dụng địa chỉ đó, hàm hoán đổi trao đổi các giá trị của chỉ mục thứ nhất và thứ hai của mảng. Đây vẫn là giá trị truyền qua vì địa chỉ là thứ được sao chép vào hàm hoán đổi

Mặc dù về mặt kỹ thuật, có một cách để sao chép các byte của một mảng làm tham số cho một hàm, nhưng nó liên quan đến việc khởi tạo một mảng bên trong một cấu trúc và sau đó chuyển cấu trúc đó cho một hàm và theo ý kiến ​​của tôi thì hơi phức tạp. Và ngay cả khi làm điều đó, nó vẫn là giá trị truyền qua về mặt kỹ thuật

Phần kết luận

Tôi hy vọng bài đăng này đã giúp làm rõ cách mọi thứ được truyền theo giá trị trong C. Như mọi khi tôi mở cho ý kiến ​​​​và đề xuất

C có sử dụng pass by value không?

C luôn sử dụng 'truyền theo giá trị' để truyền đối số cho hàm (một thuật ngữ khác là 'gọi theo giá trị', có nghĩa giống như vậy), có nghĩa là mã trong một .

Truyền theo giá trị với ví dụ là gì?

"Truyền theo giá trị" có nghĩa là bạn chuyển giá trị thực của biến vào hàm . Vì vậy, trong ví dụ của bạn, nó sẽ vượt qua giá trị 9. "Chuyển theo tham chiếu" có nghĩa là bạn chuyển chính biến đó vào hàm (không chỉ giá trị). Vì vậy, trong ví dụ của bạn, nó sẽ truyền một đối tượng số nguyên có giá trị là 9.

Giá trị đi qua là gì?

Theo định nghĩa, truyền theo giá trị có nghĩa là bạn đang tạo một bản sao trong bộ nhớ của giá trị của tham số thực được truyền vào, một bản sao nội dung của tham số thực. Use pass by value when when you are only "using" the parameter for some computation, not changing it for the client program.

Có vượt qua giá trị sử dụng con trỏ trong C không?

Trong C, tất cả các tham số hàm được truyền theo giá trị. Chỉ là một số giá trị có thể là con trỏ .