Hướng dẫn pass in c++ - vượt qua trong c ++

Mở đầu

Khi học một ngôn ngữ lập trình, một trong những thứ bạn phải nắm được đó là ngôn ngữ đó truyền biến vào hàm bằng cách nào, khi thao tác với biến đó trong hàm thì có ảnh hưởng tới biến nằm ngoài hàm hay không? Điều này là rất cần thiết để tránh những khó hiểu về sau, nhất là những người đang code một ngôn ngữ quen rồi nhảy sang ngôn ngữ khác học.

Show

Nội dung chính ShowShow

  • Mở đầu
  • Kiến thức chung
  • C và C++ pass-by-value như thế nào?
  • Đoạn code trên sẽ in ra như sau:
  • Vì var a = 1 pass(a) function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào. // dùng a ở đây. }6 và // Đoạn code này giống nhau trong C và C++ #include #include void test(int b) { printf("Địa chỉ của b trước khi gán: %d\n", &b); b = 2; printf("Địa chỉ của b sau khi gán: %d\n", &b); } int main() { int a = 1; printf("Địa chỉ của a trước khi truyền vào hàm: %d\n", &a); test(a); printf("Địa chỉ của a sau khi gọi hàm: %d\n", &a); printf("Giá trị của a sau khi gọi hàm: %d\n", a); }0 cùng trỏ đến một địa chỉ stack nên gán // Đoạn code này giống nhau trong C và C++ #include #include void test(int b) { printf("Địa chỉ của b trước khi gán: %d\n", &b); b = 2; printf("Địa chỉ của b sau khi gán: %d\n", &b); } int main() { int a = 1; printf("Địa chỉ của a trước khi truyền vào hàm: %d\n", &a); test(a); printf("Địa chỉ của a sau khi gọi hàm: %d\n", &a); printf("Giá trị của a sau khi gọi hàm: %d\n", a); }0 ở trong hàm cũng làm var a = 1 pass(a) function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào. // dùng a ở đây. }6 ở ngoài hàm bị thay đổi.
  • Tất cả các kiểu primitive trong js đều là immutable.
  • Một số thứ cần biết trong js
  • Javascript pass-by-value hay pass-by-reference
  • {item: [1, 2]}
  • Mô tả bằng hình ảnh

Ví dụ 2 đoạn code dưới đây giống nhau nhưng kết quả lại trả về khác nhau cho mỗi ngôn ngữ:

// javascript

function test(b) {
  b[0] = 3
}

var a = [1, 2]
test(a)
console.log(a)  // [3, 2]
// PHP

function test($b) {
  $b[0] = 3;
}

$a = [1, 2];
test($a);
var_dump($a)  // [1, 2]

Các ngôn ngữ khác nhau có cách xử lý với các tham số truyền vào khác nhau nhưng có 2 loại truyền tham số đó là truyền theo giá trị (pass-by-value) hay truyền theo tham chiếu (pass-by-reference). Có một số ngôn ngữ có thêm khái niệm pass-by-sharing nhưng khái niệm này thực chất cùng bản chất với 2 khái niệm trên.tham số truyền vào khác nhau nhưng có 2 loại truyền tham số đó là truyền theo giá trị (pass-by-value) hay truyền theo tham chiếu (pass-by-reference). Có một số ngôn ngữ có thêm khái niệm pass-by-sharing nhưng khái niệm này thực chất cùng bản chất với 2 khái niệm trên.tham số truyền vào khác nhau nhưng có 2 loại truyền tham số đó là truyền theo giá trị (pass-by-value) hay truyền theo tham chiếu (pass-by-reference). Có một số ngôn ngữ có thêm khái niệm pass-by-sharing nhưng khái niệm này thực chất cùng bản chất với 2 khái niệm trên.

Trước khi đọc bài này, cần nắm được cơ bản một số thứ sau:

  • Mutable và immutable là gì?
  • Biến được lưu trữ trên stack như thế nào?

Mình sẽ trình bày cho một số ngôn ngữ là C, C++, js, ruby, java, php.C, C++, js, ruby, java, php.C, C++, js, ruby, java, php.

Phần giải thích dưới đây mình cố gắng bám sát vào việc mô tả bộ nhớ để trình bày nên có lẽ sẽ hơi khó hiểu vì chỉ có bảng mà không có hình ảnh trực quan.

Nếu bạn muốn bỏ qua phần mô tả bộ nhớ và xem bằng hình ảnh thì nhảy xuống phần Mô tả bằng hình ảnh.

Kiến thức chung

  • C và C++ pass-by-value như thế nào? xử lý dữ liệu thông qua địa chỉ bộ nhớ nên thứ được truyền vào hàm luôn luôn là địa chỉ bộ nhớ chứ không phải là giá trị.
  • Đoạn code trên sẽ in ra như sau: và pass-by-reference không có định nghĩa cụ thể nào và có thể hiểu khác nhau với từng ngôn ngữ. Nhưng đều có chung một nguyên lý là:
  • Vì var a = 1 pass(a) function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào. // dùng a ở đây. }6 và // Đoạn code này giống nhau trong C và C++ #include #include void test(int b) { printf("Địa chỉ của b trước khi gán: %d\n", &b); b = 2; printf("Địa chỉ của b sau khi gán: %d\n", &b); } int main() { int a = 1; printf("Địa chỉ của a trước khi truyền vào hàm: %d\n", &a); test(a); printf("Địa chỉ của a sau khi gọi hàm: %d\n", &a); printf("Giá trị của a sau khi gọi hàm: %d\n", a); }0 cùng trỏ đến một địa chỉ stack nên gán // Đoạn code này giống nhau trong C và C++ #include #include void test(int b) { printf("Địa chỉ của b trước khi gán: %d\n", &b); b = 2; printf("Địa chỉ của b sau khi gán: %d\n", &b); } int main() { int a = 1; printf("Địa chỉ của a trước khi truyền vào hàm: %d\n", &a); test(a); printf("Địa chỉ của a sau khi gọi hàm: %d\n", &a); printf("Giá trị của a sau khi gọi hàm: %d\n", a); }0 ở trong hàm cũng làm var a = 1 pass(a) function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào. // dùng a ở đây. }6 ở ngoài hàm bị thay đổi. được hiểu là khi bạn thay đổi biến trong hàm thì ngoài hàm sẽ không bị ảnh hưởng. Nó giống như bạn copy giá trị của biến vào biến khác rồi truyền vào hàm.
  • Tất cả các kiểu primitive trong js đều là immutable. là khi bạn thay đổi biến trong hàm cũng làm ngoài hàm bị ảnh hưởng. Nó giống như bạn truyền đúng địa chỉ của biến đó vào hàm.
  • Một số thứ cần biết trong jsRAM có thể được lưu trữ trên stack hoặc heap nhưng việc tham chiếu bằng địa chỉ giữa các biến là như nhau nên để cho đơn giản mình sẽ giả sử chúng chỉ được lưu trữ trên stack.
  • Trong tất cả ngôn ngữ, khi khai báo một hàm thì tham số của hàm có thể khác hoặc trùng với tên biến được truyền vào hàm., khi khai báo một hàm thì tham số của hàm có thể khác hoặc trùng với tên biến được truyền vào hàm., khi khai báo một hàm thì tham số của hàm có thể khác hoặc trùng với tên biến được truyền vào hàm.

Ví dụ 2 đoạn code dưới đây là hoàn toàn như nhau:

var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
var a = 1
pass(a)

function pass(b) {
  // dùng b ở đây
}

C, C++

var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
4
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
5.

C và C++ pass-by-value như thế nào?

// Đoạn code này giống nhau trong C và C++

#include <iostream>
#include <string>

void test(int b) {
  printf("Địa chỉ của b trước khi gán: %d\n", &b);
  b = 2;
  printf("Địa chỉ của b sau khi gán: %d\n", &b);
}
    
int main()
{
    int a = 1;
    printf("Địa chỉ của a trước khi truyền vào hàm: %d\n", &a);    
    
    test(a);
    
    printf("Địa chỉ của a sau khi gọi hàm: %d\n", &a);
    printf("Giá trị của a sau khi gọi hàm: %d\n", a);
}

Biến

var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 trên trong bảng symbol table sẽ như sau:
Tên biếnĐịa chỉ của biến trên stackGiá trị của biến trong stack
a ssss1 1

Khi gọi hàm

var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
7 từ hàm
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
8 thì biến
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 sẽ được copy thành một biến mới và địa chỉ của biến mới này sẽ được truyền vào hàm
var a = 1
pass(a)

function pass(b) {
  // dùng b ở đây
}
0:
Tên biếnĐịa chỉ của biến trên stackGiá trị của biến trong stack
a ssss1 1
Khi gọi hàm
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
7 từ hàm
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
8 thì biến
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 sẽ được copy thành một biến mới và địa chỉ của biến mới này sẽ được truyền vào hàm
var a = 1
pass(a)

function pass(b) {
  // dùng b ở đây
}
0:
1

Khi gọi hàm

var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
7 từ hàm
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
8 thì biến
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 sẽ được copy thành một biến mới và địa chỉ của biến mới này sẽ được truyền vào hàm
var a = 1
pass(a)

function pass(b) {
  // dùng b ở đây
}
0: CC++ có kiểu intmutable nên câu lệnh

b
Tên biếnĐịa chỉ của biến trên stackGiá trị của biến trong stack
a ssss1 1
Khi gọi hàm
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
7 từ hàm
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
8 thì biến
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 sẽ được copy thành một biến mới và địa chỉ của biến mới này sẽ được truyền vào hàm
var a = 1
pass(a)

function pass(b) {
  // dùng b ở đây
}
0:
2

Khi gọi hàm

var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
7 từ hàm
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
8 thì biến
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 sẽ được copy thành một biến mới và địa chỉ của biến mới này sẽ được truyền vào hàm
var a = 1
pass(a)

function pass(b) {
  // dùng b ở đây
}
0:

b

ssss2 C và C++ có kiểu int là mutable nên câu lệnh

var a = 1
pass(a)

function pass(b) {
  // dùng b ở đây
}
1 sẽ tạo:

ssss2 C sẽ biết C có thể thay đổi giá trị của biến ngoài hàm bằng cách truyền con trỏ (pointer), điều này vẫn đúng khi nói C là pass-by-value vì:

Vì C và C++ có kiểu int là mutable nên câu lệnh

var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6

var a = 1
pass(a)

function pass(b) {
  // dùng b ở đây
}
1 sẽ tạo:
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
2

  • Như bạn thấy biến
  • var a = 1
    pass(a)
    
    function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
      // dùng a ở đây.
    }
    6 vẫn trỏ tới
    var a = 1
    pass(a)
    
    function pass(b) {
      // dùng b ở đây
    }
    3 và vẫn có giá trị là
    var a = 1
    pass(a)
    
    function pass(b) {
      // dùng b ở đây
    }
    4 không hề bị ảnh hưởng.C sẽ biết C có thể thay đổi giá trị của biến ngoài hàm bằng cách truyền con trỏ (pointer), điều này vẫn đúng khi nói C là pass-by-value vì:biến khác và truyền địa chỉ của biến khác này vào hàm
    var a = 1
    pass(a)
    
    function pass(b) {
      // dùng b ở đây
    }
    0 (trong hàm
    var a = 1
    pass(a)
    
    function pass(b) {
      // dùng b ở đây
    }
    0 thì địa chỉ của biến khác này chính là
    // Đoạn code này giống nhau trong C và C++
    
    #include <iostream>
    #include <string>
    
    void test(int b) {
      printf("Địa chỉ của b trước khi gán: %d\n", &b);
      b = 2;
      printf("Địa chỉ của b sau khi gán: %d\n", &b);
    }
        
    int main()
    {
        int a = 1;
        printf("Địa chỉ của a trước khi truyền vào hàm: %d\n", &a);    
        
        test(a);
        
        printf("Địa chỉ của a sau khi gọi hàm: %d\n", &a);
        printf("Giá trị của a sau khi gọi hàm: %d\n", a);
    }
    0).
Tên biếnĐịa chỉ của biến trên stackGiá trị của biến trong stack
a ssss1 1
Khi gọi hàm
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
7 từ hàm
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
8 thì biến
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 sẽ được copy thành một biến mới và địa chỉ của biến mới này sẽ được truyền vào hàm
var a = 1
pass(a)

function pass(b) {
  // dùng b ở đây
}
0:
ssss1

Khi gọi hàm

var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
7 từ hàm
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
8 thì biến
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 sẽ được copy thành một biến mới và địa chỉ của biến mới này sẽ được truyền vào hàm
var a = 1
pass(a)

function pass(b) {
  // dùng b ở đây
}
0:

var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
7 từ hàm
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
8 thì biến
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 sẽ được copy thành một biến mới và địa chỉ của biến mới này sẽ được truyền vào hàm
var a = 1
pass(a)

function pass(b) {
  // dùng b ở đây
}
0:

Khi gọi hàm

var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
7 từ hàm
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
8 thì biến
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 sẽ được copy thành một biến mới và địa chỉ của biến mới này sẽ được truyền vào hàm
var a = 1
pass(a)

function pass(b) {
  // dùng b ở đây
}
0:

b

ssss2 C và C++ có kiểu int là mutable nên câu lệnh symbol table sẽ như sau:
Tên biếnĐịa chỉ của biến trên stackGiá trị của biến trong stack
a ssss1 2
Khi gọi hàm
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
7 từ hàm
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
8 thì biến
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 sẽ được copy thành một biến mới và địa chỉ của biến mới này sẽ được truyền vào hàm
var a = 1
pass(a)

function pass(b) {
  // dùng b ở đây
}
0:
ssss1

Khi gọi hàm

var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
7 từ hàm
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
8 thì biến
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 sẽ được copy thành một biến mới và địa chỉ của biến mới này sẽ được truyền vào hàm
var a = 1
pass(a)

function pass(b) {
  // dùng b ở đây
}
0:

Khi gọi hàm

var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
7 từ hàm
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
8 thì biến
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 sẽ được copy thành một biến mới và địa chỉ của biến mới này sẽ được truyền vào hàm
var a = 1
pass(a)

function pass(b) {
  // dùng b ở đây
}
0: con trỏ vào hàm thì vẫn copy địa chỉ sang biến khác rồi truyền vào hàm nên nó vẫn là pass-by-value (một số người gọi truyền theo pointer là pass-by-address).

Khi gọi hàm var a = 1 pass(a) function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào. // dùng a ở đây. }7 từ hàm var a = 1 pass(a) function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào. // dùng a ở đây. }8 thì biến var a = 1 pass(a) function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào. // dùng a ở đây. }6 sẽ được copy thành một biến mới và địa chỉ của biến mới này sẽ được truyền vào hàm var a = 1 pass(a) function pass(b) { // dùng b ở đây }0:

b

ssss2 C và C++ có kiểu int là mutable nên câu lệnh C nếu muốn thay đổi giá trị của biến ngoài hàm từ trong hàm thì phải truyền con trỏ như giải thích ở trên. Nhược điểm của phương pháp này là:
  • var a = 1
    pass(a)
    
    function pass(b) {
      // dùng b ở đây
    }
    1 sẽ tạo: pointer trong stack.
  • ssss2 asterisk (dấu *) vào trước tên biến.

VD: 

var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
0

Vì C và C++ có kiểu int là mutable nên câu lệnh C++ có giải pháp thay thế là pass-by-reference giúp ít nhất là tránh các nhược điểm trên:

var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
1

var a = 1
pass(a)

function pass(b) {
  // dùng b ở đây
}
1 sẽ tạo:
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
2pass-by-reference:

// PHP

function test($b) {
  $b[0] = 3;
}

$a = [1, 2];
test($a);
var_dump($a)  // [1, 2]
0

Như bạn thấy biến symbol table trước khi thực thi sẽ như sau:

Tên biếnĐịa chỉ của biến trên stackGiá trị của biến trong stack
a ssss1 1
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
7 từ hàm
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
8 thì biến
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 sẽ được copy thành một biến mới và địa chỉ của biến mới này sẽ được truyền vào hàm
var a = 1
pass(a)

function pass(b) {
  // dùng b ở đây
}
0:
ssss1
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
7 từ hàm
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
8 thì biến
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 sẽ được copy thành một biến mới và địa chỉ của biến mới này sẽ được truyền vào hàm
var a = 1
pass(a)

function pass(b) {
  // dùng b ở đây
}
0:

Khi gọi hàm

var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
7 từ hàm
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
8 thì biến
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 sẽ được copy thành một biến mới và địa chỉ của biến mới này sẽ được truyền vào hàm
var a = 1
pass(a)

function pass(b) {
  // dùng b ở đây
}
0:

Tên biếnĐịa chỉ của biến trên stackGiá trị của biến trong stack
a ssss1 2
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
7 từ hàm
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
8 thì biến
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 sẽ được copy thành một biến mới và địa chỉ của biến mới này sẽ được truyền vào hàm
var a = 1
pass(a)

function pass(b) {
  // dùng b ở đây
}
0:
ssss1
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
7 từ hàm
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
8 thì biến
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 sẽ được copy thành một biến mới và địa chỉ của biến mới này sẽ được truyền vào hàm
var a = 1
pass(a)

function pass(b) {
  // dùng b ở đây
}
0:

Khi gọi hàm

var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
7 từ hàm
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
8 thì biến
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 sẽ được copy thành một biến mới và địa chỉ của biến mới này sẽ được truyền vào hàm
var a = 1
pass(a)

function pass(b) {
  // dùng b ở đây
}
0: địa chỉ stack nên gán

b

ssss2 C và C++ có kiểu int là mutable nên câu lệnh symbol table trên có thêm biến

var a = 1
pass(a)

function pass(b) {
  // dùng b ở đây
}
1 sẽ tạo: stack không phải cấp phát thêm một vùng bộ nhớ cho
// Đoạn code này giống nhau trong C và C++

#include <iostream>
#include <string>

void test(int b) {
  printf("Địa chỉ của b trước khi gán: %d\n", &b);
  b = 2;
  printf("Địa chỉ của b sau khi gán: %d\n", &b);
}
    
int main()
{
    int a = 1;
    printf("Địa chỉ của a trước khi truyền vào hàm: %d\n", &a);    
    
    test(a);
    
    printf("Địa chỉ của a sau khi gọi hàm: %d\n", &a);
    printf("Giá trị của a sau khi gọi hàm: %d\n", a);
}
0 vì sử dụng chung
var a = 1
pass(a)

function pass(b) {
  // dùng b ở đây
}
3 với
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6.

2

// PHP

function test($b) {
  $b[0] = 3;
}

$a = [1, 2];
test($a);
var_dump($a)  // [1, 2]
1

Vì var a = 1 pass(a) function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào. // dùng a ở đây. }6 và // Đoạn code này giống nhau trong C và C++ #include #include void test(int b) { printf("Địa chỉ của b trước khi gán: %d\n", &b); b = 2; printf("Địa chỉ của b sau khi gán: %d\n", &b); } int main() { int a = 1; printf("Địa chỉ của a trước khi truyền vào hàm: %d\n", &a); test(a); printf("Địa chỉ của a sau khi gọi hàm: %d\n", &a); printf("Giá trị của a sau khi gọi hàm: %d\n", a); }0 cùng trỏ đến một địa chỉ stack nên gán // Đoạn code này giống nhau trong C và C++ #include #include void test(int b) { printf("Địa chỉ của b trước khi gán: %d\n", &b); b = 2; printf("Địa chỉ của b sau khi gán: %d\n", &b); } int main() { int a = 1; printf("Địa chỉ của a trước khi truyền vào hàm: %d\n", &a); test(a); printf("Địa chỉ của a sau khi gọi hàm: %d\n", &a); printf("Giá trị của a sau khi gọi hàm: %d\n", a); }0 ở trong hàm cũng làm var a = 1 pass(a) function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào. // dùng a ở đây. }6 ở ngoài hàm bị thay đổi.

  • Trong bảng symbol table trên có thêm biến
    // Đoạn code này giống nhau trong C và C++
    
    #include <iostream>
    #include <string>
    
    void test(int b) {
      printf("Địa chỉ của b trước khi gán: %d\n", &b);
      b = 2;
      printf("Địa chỉ của b sau khi gán: %d\n", &b);
    }
        
    int main()
    {
        int a = 1;
        printf("Địa chỉ của a trước khi truyền vào hàm: %d\n", &a);    
        
        test(a);
        
        printf("Địa chỉ của a sau khi gọi hàm: %d\n", &a);
        printf("Giá trị của a sau khi gọi hàm: %d\n", a);
    }
    0 nhưng trong stack không phải cấp phát thêm một vùng bộ nhớ cho
    // Đoạn code này giống nhau trong C và C++
    
    #include <iostream>
    #include <string>
    
    void test(int b) {
      printf("Địa chỉ của b trước khi gán: %d\n", &b);
      b = 2;
      printf("Địa chỉ của b sau khi gán: %d\n", &b);
    }
        
    int main()
    {
        int a = 1;
        printf("Địa chỉ của a trước khi truyền vào hàm: %d\n", &a);    
        
        test(a);
        
        printf("Địa chỉ của a sau khi gọi hàm: %d\n", &a);
        printf("Giá trị của a sau khi gọi hàm: %d\n", a);
    }
    0 vì sử dụng chung
    var a = 1
    pass(a)
    
    function pass(b) {
      // dùng b ở đây
    }
    3 với
    var a = 1
    pass(a)
    
    function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
      // dùng a ở đây.
    }
    6.primitive trong js đều là immutable.primitive trong js đều là immutable.
  • Javascriptprimitive với nhau thì chúng sẽ so sánh giá trị.primitive với nhau thì chúng sẽ so sánh giá trị.
// PHP

function test($b) {
  $b[0] = 3;
}

$a = [1, 2];
test($a);
var_dump($a)  // [1, 2]
2
  • Một số thứ cần biết trong jsobject (không phải các kiểu primitive) thì chúng sẽ so sánh địa chỉ của 2 object đó với nhau.object (không phải các kiểu primitive) thì chúng sẽ so sánh địa chỉ của 2 object đó với nhau.
// PHP

function test($b) {
  $b[0] = 3;
}

$a = [1, 2];
test($a);
var_dump($a)  // [1, 2]
3

Tất cả các kiểu primitive trong js đều là immutable.

Khi so sánh 2 biến có kiểu primitive với nhau thì chúng sẽ so sánh giá trị.pass-by-value, cũng nhiều người nói js vừa có pass-by-value, vừa có pass-by-reference. Nhưng:pass-by-value, cũng nhiều người nói js vừa có pass-by-value, vừa có pass-by-reference. Nhưng:

var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
29

Nhưng khi so sánh 2 kiểu object (không phải các kiểu primitive) thì chúng sẽ so sánh địa chỉ của 2 object đó với nhau. truyền cùng một địa chỉ với biến vào hàm chứ không copy sang biến khác giống C. truyền cùng một địa chỉ với biến vào hàm chứ không copy sang biến khác giống C.

Javascript pass-by-value hay pass-by-referenceobject a và object b bằng nhau nên chúng sẽ có chung một địa chỉ trên stack.object a và object b bằng nhau nên chúng sẽ có chung một địa chỉ trên stack.

Tên biếnĐịa chỉ của biến trên stackGiá trị của biến trong stack
a ssss1 b
b ssss1 b
1 Sau khi thực thi sẽ như sau: 2

var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 và
// Đoạn code này giống nhau trong C và C++

#include <iostream>
#include <string>

void test(int b) {
  printf("Địa chỉ của b trước khi gán: %d\n", &b);
  b = 2;
  printf("Địa chỉ của b sau khi gán: %d\n", &b);
}
    
int main()
{
    int a = 1;
    printf("Địa chỉ của a trước khi truyền vào hàm: %d\n", &a);    
    
    test(a);
    
    printf("Địa chỉ của a sau khi gọi hàm: %d\n", &a);
    printf("Giá trị của a sau khi gọi hàm: %d\n", a);
}
0 cùng trỏ đến một địa chỉ stack nên gán
// Đoạn code này giống nhau trong C và C++

#include <iostream>
#include <string>

void test(int b) {
  printf("Địa chỉ của b trước khi gán: %d\n", &b);
  b = 2;
  printf("Địa chỉ của b sau khi gán: %d\n", &b);
}
    
int main()
{
    int a = 1;
    printf("Địa chỉ của a trước khi truyền vào hàm: %d\n", &a);    
    
    test(a);
    
    printf("Địa chỉ của a sau khi gọi hàm: %d\n", &a);
    printf("Giá trị của a sau khi gọi hàm: %d\n", a);
}
0 ở trong hàm cũng làm
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 ở ngoài hàm bị thay đổi.
Tên biếnĐịa chỉ của biến trên stackGiá trị của biến trong stack
a ssss1 b
1 Sau khi thực thi sẽ như sau: 2
b 1 b
1 Sau khi thực thi sẽ như sau: 2

var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 và
// Đoạn code này giống nhau trong C và C++

#include <iostream>
#include <string>

void test(int b) {
  printf("Địa chỉ của b trước khi gán: %d\n", &b);
  b = 2;
  printf("Địa chỉ của b sau khi gán: %d\n", &b);
}
    
int main()
{
    int a = 1;
    printf("Địa chỉ của a trước khi truyền vào hàm: %d\n", &a);    
    
    test(a);
    
    printf("Địa chỉ của a sau khi gọi hàm: %d\n", &a);
    printf("Giá trị của a sau khi gọi hàm: %d\n", a);
}
0 cùng trỏ đến một địa chỉ stack nên gán
// Đoạn code này giống nhau trong C và C++

#include <iostream>
#include <string>

void test(int b) {
  printf("Địa chỉ của b trước khi gán: %d\n", &b);
  b = 2;
  printf("Địa chỉ của b sau khi gán: %d\n", &b);
}
    
int main()
{
    int a = 1;
    printf("Địa chỉ của a trước khi truyền vào hàm: %d\n", &a);    
    
    test(a);
    
    printf("Địa chỉ của a sau khi gọi hàm: %d\n", &a);
    printf("Giá trị của a sau khi gọi hàm: %d\n", a);
}
0 ở trong hàm cũng làm
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 ở ngoài hàm bị thay đổi.

var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 và
// Đoạn code này giống nhau trong C và C++

#include <iostream>
#include <string>

void test(int b) {
  printf("Địa chỉ của b trước khi gán: %d\n", &b);
  b = 2;
  printf("Địa chỉ của b sau khi gán: %d\n", &b);
}
    
int main()
{
    int a = 1;
    printf("Địa chỉ của a trước khi truyền vào hàm: %d\n", &a);    
    
    test(a);
    
    printf("Địa chỉ của a sau khi gọi hàm: %d\n", &a);
    printf("Giá trị của a sau khi gọi hàm: %d\n", a);
}
0 cùng trỏ đến một địa chỉ stack nên gán
// Đoạn code này giống nhau trong C và C++

#include <iostream>
#include <string>

void test(int b) {
  printf("Địa chỉ của b trước khi gán: %d\n", &b);
  b = 2;
  printf("Địa chỉ của b sau khi gán: %d\n", &b);
}
    
int main()
{
    int a = 1;
    printf("Địa chỉ của a trước khi truyền vào hàm: %d\n", &a);    
    
    test(a);
    
    printf("Địa chỉ của a sau khi gọi hàm: %d\n", &a);
    printf("Giá trị của a sau khi gọi hàm: %d\n", a);
}
0 ở trong hàm cũng làm
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 ở ngoài hàm bị thay đổi.

Trong bảng symbol table trên có thêm biến

// Đoạn code này giống nhau trong C và C++

#include <iostream>
#include <string>

void test(int b) {
  printf("Địa chỉ của b trước khi gán: %d\n", &b);
  b = 2;
  printf("Địa chỉ của b sau khi gán: %d\n", &b);
}
    
int main()
{
    int a = 1;
    printf("Địa chỉ của a trước khi truyền vào hàm: %d\n", &a);    
    
    test(a);
    
    printf("Địa chỉ của a sau khi gọi hàm: %d\n", &a);
    printf("Giá trị của a sau khi gọi hàm: %d\n", a);
}
0 nhưng trong stack không phải cấp phát thêm một vùng bộ nhớ cho
// Đoạn code này giống nhau trong C và C++

#include <iostream>
#include <string>

void test(int b) {
  printf("Địa chỉ của b trước khi gán: %d\n", &b);
  b = 2;
  printf("Địa chỉ của b sau khi gán: %d\n", &b);
}
    
int main()
{
    int a = 1;
    printf("Địa chỉ của a trước khi truyền vào hàm: %d\n", &a);    
    
    test(a);
    
    printf("Địa chỉ của a sau khi gọi hàm: %d\n", &a);
    printf("Giá trị của a sau khi gọi hàm: %d\n", a);
}
0 vì sử dụng chung
var a = 1
pass(a)

function pass(b) {
  // dùng b ở đây
}
3 với
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6.
// PHP

function test($b) {
  $b[0] = 3;
}

$a = [1, 2];
test($a);
var_dump($a)  // [1, 2]
4
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
66

Tên biếnĐịa chỉ của biến trên stackGiá trị của biến trong stack
a ssss1 3
b ssss1 3

b

Tên biếnĐịa chỉ của biến trên stackGiá trị của biến trong stack
a ssss1 3
b 1 4


Sau khi thực thi sẽ như sau:

2

// PHP

function test($b) {
  $b[0] = 3;
}

$a = [1, 2];
test($a);
var_dump($a)  // [1, 2]
5

var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 và
// Đoạn code này giống nhau trong C và C++

#include <iostream>
#include <string>

void test(int b) {
  printf("Địa chỉ của b trước khi gán: %d\n", &b);
  b = 2;
  printf("Địa chỉ của b sau khi gán: %d\n", &b);
}
    
int main()
{
    int a = 1;
    printf("Địa chỉ của a trước khi truyền vào hàm: %d\n", &a);    
    
    test(a);
    
    printf("Địa chỉ của a sau khi gọi hàm: %d\n", &a);
    printf("Giá trị của a sau khi gọi hàm: %d\n", a);
}
0 cùng trỏ đến một địa chỉ stack nên gán
// Đoạn code này giống nhau trong C và C++

#include <iostream>
#include <string>

void test(int b) {
  printf("Địa chỉ của b trước khi gán: %d\n", &b);
  b = 2;
  printf("Địa chỉ của b sau khi gán: %d\n", &b);
}
    
int main()
{
    int a = 1;
    printf("Địa chỉ của a trước khi truyền vào hàm: %d\n", &a);    
    
    test(a);
    
    printf("Địa chỉ của a sau khi gọi hàm: %d\n", &a);
    printf("Giá trị của a sau khi gọi hàm: %d\n", a);
}
0 ở trong hàm cũng làm
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 ở ngoài hàm bị thay đổi.

var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 và
// Đoạn code này giống nhau trong C và C++

#include <iostream>
#include <string>

void test(int b) {
  printf("Địa chỉ của b trước khi gán: %d\n", &b);
  b = 2;
  printf("Địa chỉ của b sau khi gán: %d\n", &b);
}
    
int main()
{
    int a = 1;
    printf("Địa chỉ của a trước khi truyền vào hàm: %d\n", &a);    
    
    test(a);
    
    printf("Địa chỉ của a sau khi gọi hàm: %d\n", &a);
    printf("Giá trị của a sau khi gọi hàm: %d\n", a);
}
0 cùng trỏ đến một địa chỉ stack nên gán
// Đoạn code này giống nhau trong C và C++

#include <iostream>
#include <string>

void test(int b) {
  printf("Địa chỉ của b trước khi gán: %d\n", &b);
  b = 2;
  printf("Địa chỉ của b sau khi gán: %d\n", &b);
}
    
int main()
{
    int a = 1;
    printf("Địa chỉ của a trước khi truyền vào hàm: %d\n", &a);    
    
    test(a);
    
    printf("Địa chỉ của a sau khi gọi hàm: %d\n", &a);
    printf("Giá trị của a sau khi gọi hàm: %d\n", a);
}
0 ở trong hàm cũng làm
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 ở ngoài hàm bị thay đổi.

Trong bảng symbol table trên có thêm biến stack:
Tên biếnĐịa chỉ của biến trên stackGiá trị của biến trong stack
a ssss1 b
b ssss1 b
1 Sau khi thực thi sẽ như sau: 2


var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 và
// Đoạn code này giống nhau trong C và C++

#include <iostream>
#include <string>

void test(int b) {
  printf("Địa chỉ của b trước khi gán: %d\n", &b);
  b = 2;
  printf("Địa chỉ của b sau khi gán: %d\n", &b);
}
    
int main()
{
    int a = 1;
    printf("Địa chỉ của a trước khi truyền vào hàm: %d\n", &a);    
    
    test(a);
    
    printf("Địa chỉ của a sau khi gọi hàm: %d\n", &a);
    printf("Giá trị của a sau khi gọi hàm: %d\n", a);
}
0 cùng trỏ đến một địa chỉ stack nên gán
// Đoạn code này giống nhau trong C và C++

#include <iostream>
#include <string>

void test(int b) {
  printf("Địa chỉ của b trước khi gán: %d\n", &b);
  b = 2;
  printf("Địa chỉ của b sau khi gán: %d\n", &b);
}
    
int main()
{
    int a = 1;
    printf("Địa chỉ của a trước khi truyền vào hàm: %d\n", &a);    
    
    test(a);
    
    printf("Địa chỉ của a sau khi gọi hàm: %d\n", &a);
    printf("Giá trị của a sau khi gọi hàm: %d\n", a);
}
0 ở trong hàm cũng làm
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 ở ngoài hàm bị thay đổi.

var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 và
// Đoạn code này giống nhau trong C và C++

#include <iostream>
#include <string>

void test(int b) {
  printf("Địa chỉ của b trước khi gán: %d\n", &b);
  b = 2;
  printf("Địa chỉ của b sau khi gán: %d\n", &b);
}
    
int main()
{
    int a = 1;
    printf("Địa chỉ của a trước khi truyền vào hàm: %d\n", &a);    
    
    test(a);
    
    printf("Địa chỉ của a sau khi gọi hàm: %d\n", &a);
    printf("Giá trị của a sau khi gọi hàm: %d\n", a);
}
0 cùng trỏ đến một địa chỉ stack nên gán
// Đoạn code này giống nhau trong C và C++

#include <iostream>
#include <string>

void test(int b) {
  printf("Địa chỉ của b trước khi gán: %d\n", &b);
  b = 2;
  printf("Địa chỉ của b sau khi gán: %d\n", &b);
}
    
int main()
{
    int a = 1;
    printf("Địa chỉ của a trước khi truyền vào hàm: %d\n", &a);    
    
    test(a);
    
    printf("Địa chỉ của a sau khi gọi hàm: %d\n", &a);
    printf("Giá trị của a sau khi gọi hàm: %d\n", a);
}
0 ở trong hàm cũng làm
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 ở ngoài hàm bị thay đổi.

Trong bảng symbol table trên có thêm biến changed", lúc đó stack sẽ thành:
Tên biếnĐịa chỉ của biến trên stackGiá trị của biến trong stack
a ssss1 b
b ssss1 b
1 Sau khi thực thi sẽ như sau: 2
1 Sau khi thực thi sẽ như sau: 2

var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 và
// Đoạn code này giống nhau trong C và C++

#include <iostream>
#include <string>

void test(int b) {
  printf("Địa chỉ của b trước khi gán: %d\n", &b);
  b = 2;
  printf("Địa chỉ của b sau khi gán: %d\n", &b);
}
    
int main()
{
    int a = 1;
    printf("Địa chỉ của a trước khi truyền vào hàm: %d\n", &a);    
    
    test(a);
    
    printf("Địa chỉ của a sau khi gọi hàm: %d\n", &a);
    printf("Giá trị của a sau khi gọi hàm: %d\n", a);
}
0 cùng trỏ đến một địa chỉ stack nên gán
// Đoạn code này giống nhau trong C và C++

#include <iostream>
#include <string>

void test(int b) {
  printf("Địa chỉ của b trước khi gán: %d\n", &b);
  b = 2;
  printf("Địa chỉ của b sau khi gán: %d\n", &b);
}
    
int main()
{
    int a = 1;
    printf("Địa chỉ của a trước khi truyền vào hàm: %d\n", &a);    
    
    test(a);
    
    printf("Địa chỉ của a sau khi gọi hàm: %d\n", &a);
    printf("Giá trị của a sau khi gọi hàm: %d\n", a);
}
0 ở trong hàm cũng làm
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 ở ngoài hàm bị thay đổi. immutable.

var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 và
// Đoạn code này giống nhau trong C và C++

#include <iostream>
#include <string>

void test(int b) {
  printf("Địa chỉ của b trước khi gán: %d\n", &b);
  b = 2;
  printf("Địa chỉ của b sau khi gán: %d\n", &b);
}
    
int main()
{
    int a = 1;
    printf("Địa chỉ của a trước khi truyền vào hàm: %d\n", &a);    
    
    test(a);
    
    printf("Địa chỉ của a sau khi gọi hàm: %d\n", &a);
    printf("Giá trị của a sau khi gọi hàm: %d\n", a);
}
0 cùng trỏ đến một địa chỉ stack nên gán
// Đoạn code này giống nhau trong C và C++

#include <iostream>
#include <string>

void test(int b) {
  printf("Địa chỉ của b trước khi gán: %d\n", &b);
  b = 2;
  printf("Địa chỉ của b sau khi gán: %d\n", &b);
}
    
int main()
{
    int a = 1;
    printf("Địa chỉ của a trước khi truyền vào hàm: %d\n", &a);    
    
    test(a);
    
    printf("Địa chỉ của a sau khi gọi hàm: %d\n", &a);
    printf("Giá trị của a sau khi gọi hàm: %d\n", a);
}
0 ở trong hàm cũng làm
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
6 ở ngoài hàm bị thay đổi.

Trong bảng symbol table trên có thêm biến

Javascript

Một số thứ cần biết trong js

Tất cả các kiểu primitive trong js đều là immutable.

// PHP

function test($b) {
  $b[0] = 3;
}

$a = [1, 2];
test($a);
var_dump($a)  // [1, 2]
7

Khi so sánh 2 biến có kiểu primitive với nhau thì chúng sẽ so sánh giá trị.object_id của từng object:object_id của từng object:

// PHP

function test($b) {
  $b[0] = 3;
}

$a = [1, 2];
test($a);
var_dump($a)  // [1, 2]
8

Nhưng khi so sánh 2 kiểu object (không phải các kiểu primitive) thì chúng sẽ so sánh địa chỉ của 2 object đó với nhau.

// PHP

function test($b) {
  $b[0] = 3;
}

$a = [1, 2];
test($a);
var_dump($a)  // [1, 2]
9

Javascript pass-by-value hay pass-by-reference

Nhiều người nói js chỉ pass-by-value, cũng nhiều người nói js vừa có pass-by-value, vừa có pass-by-reference. Nhưng: giống C++, cũng copy ra biến mới rồi mới truyền vào hàm (kể cả array). giống C++, cũng copy ra biến mới rồi mới truyền vào hàm (kể cả array).

Javascript truyền cùng một địa chỉ với biến vào hàm chứ không copy sang biến khác giống C.PHP5 trở đi thì kiểu object truyền vào hàm sẽ giống như javascript là truyền tham chiếu vào.PHP5 trở đi thì kiểu object truyền vào hàm sẽ giống như javascript là truyền tham chiếu vào.

var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
0

Ở ví dụ trên, trước khi

// Đoạn code này giống nhau trong C và C++

#include <iostream>
#include <string>

void test(int b) {
  printf("Địa chỉ của b trước khi gán: %d\n", &b);
  b = 2;
  printf("Địa chỉ của b sau khi gán: %d\n", &b);
}
    
int main()
{
    int a = 1;
    printf("Địa chỉ của a trước khi truyền vào hàm: %d\n", &a);    
    
    test(a);
    
    printf("Địa chỉ của a sau khi gọi hàm: %d\n", &a);
    printf("Giá trị của a sau khi gọi hàm: %d\n", a);
}
0 bị gán lại thì object a và object b bằng nhau nên chúng sẽ có chung một địa chỉ trên stack.object tương tự như javascript, còn giải thích cho các kiểu còn lại tương tự như C và C++.object tương tự như javascript, còn giải thích cho các kiểu còn lại tương tự như C và C++.

{item: [1, 2]}

var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
1

ssss1.item

var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
2

yyyy1  giải thích hoàn toàn giống javascript. giải thích hoàn toàn giống javascript.

[1, 2] java ta có thể gán bằng các phương thức mutable hoặc immutable nên symbol table có thể khác nhau phụ thuộc vào phép gán.java ta có thể gán bằng các phương thức mutable hoặc immutable nên symbol table có thể khác nhau phụ thuộc vào phép gán.

Mô tả bằng hình ảnh

Mình chỉ minh họa bằng hình ảnh đại diện cho đoạn javascript sau:javascript sau:javascript sau:

// PHP

function test($b) {
  $b[0] = 3;
}

$a = [1, 2];
test($a);
var_dump($a)  // [1, 2]
1

Trước khi phép gán xảy ra:

Hướng dẫn pass in c++ - vượt qua trong c ++

Hình ảnh mô tả cho đoạn code javascript phía trên tương tự với phần lớn các ngôn ngữ khác nhưng khác với C/C++. Như đã nói  ở phần trên, trong C/C++ thì biến

var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
11 sẽ được copy nên không trỏ vào cùng một ô nhớ với các biến khai báo giống trong hình ảnh.javascript phía trên tương tự với phần lớn các ngôn ngữ khác nhưng khác với C/C++. Như đã nói  ở phần trên, trong C/C++ thì biến
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
11 sẽ được copy nên không trỏ vào cùng một ô nhớ với các biến khai báo giống trong hình ảnh.javascript phía trên tương tự với phần lớn các ngôn ngữ khác nhưng khác với C/C++. Như đã nói  ở phần trên, trong C/C++ thì biến
var a = 1
pass(a)

function pass(a) { // tham số cũng có tên là a, trùng với tên biến sẽ được truyền vào.
  // dùng a ở đây.
}
11 sẽ được copy nên không trỏ vào cùng một ô nhớ với các biến khai báo giống trong hình ảnh.

Sau khi phép gán xảy ra:

Link tham khảo:

https://stackoverflow.com/questions/2229498/passing-by-reference-in-c

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness