Truyền giá trị trong C++

Có hai cách biến phổ biến được sử dụng để truyền đối số trong C/C++/Perl là truyền giá trị và truyền tham chiếu. Python sử dụng một cách tương tự như vậy dựa trên kiểu dữ liệu truyền vào là đối tượng bất biến hoặc đối tượng có thể thay đổi mà sử dụng giá trị truyền hoặc tham chiếu tương ứng. Hơn nữa, trong Python công việc truyền đối số cũng trở nên linh hoạt hơn nhiều nhờ vào việc hỗ trợ 2 ký tự ‘*’ và ‘**’ khi gọi hàm. Nhờ đó, chúng ta không phải viết tường minh hay cần biết trước số lượng tham số đầu vào

Phần này chúng ta sẽ làm rõ ba vấn đề sau. truyền tham trị là gì(truyền theo giá trị), truyền tham chiếu(truyền theo tham chiếu) là gì, trong java sử dụng kiểu nào ?

Mục Lục

1 – Truyền tham trị (Truyền theo giá trị)

Truyền tham trị là việc ta sao chép ra một bản sao (tạo ra một giá trị mới bằng cách sao chép giá trị gốc) và thao tác với giá trị của bản sao đó và không làm thay đổi giá trị của bản gốc. Hiểu đơn giản là khi truyền dữ liệu vào hàm và tương tác thì dữ liệu chỉ thay đổi trong hàm đó, mà không làm thay đổi giá trị ban đầu ban đầu bên ngoài hàm

package com.cafeincode.java;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class Example {
    public static void main(String[] args) {
        int counter = 7;
        log.info("Before increase:{}", counter);
        increaseValue(counter);
        log.info("After increase:{}", counter);
    }

    private static void increaseValue(int counter) {
        counter += 1;
        log.info("Increase counter:{}", counter);
    }
}
Truyền giá trị trong C++

program program as after

  • Tại dòng 7 trong hàm main(), ta khởi tạo biến counter có giá trị là 7, trước khi gọi hàm boostValue() thì giá trị của nó được giữ nguyên là 7
  • Tại dòng 9, khi gọi hàm boostValue() ta truyền biến counter có giá trị là 7 vào hàm, tuy nhiên dữ liệu của biến này đã được sao chép ra thành một biến mới, tại đây ta thực hiện cộng thêm 1 đơn vị vào biến
  • Tại dòng 10 trong hàm main(), ta thực hiện ghi giá trị biến counter, lúc này biến counter vẫn giữ nguyên giá trị của nó ban đầu do hàm boostValue() không tác động được vào giá trị của biến gốc mà chỉ tác động

2 – Truyền tham chiếu (Pass by reference)

Truyền tham chiếu là kiểu khi truyền giá trị vào hàm và thực hiện tương tác, sửa đổi thì dữ liệu ở trong hay ngoài hàm đều thay đổi, tuy nhiên trong java không có truyền tham chiếu mà chỉ có truyền tham giá trị

Một số hướng dẫn trang web hiện nay đang hướng dẫn theo kiểu. truyền biến thủy nguyên là tham trị, biến đối tượng là tham chiếu, điều này là sai hoàn toàn

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class CounterObj {
    private String value;
}

Ví dụ 1. truyền đối tượng vào hàm và khởi tạo một phiên bản mới

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class Example {

    public static void main(String[] args) {
        CounterObj counterObj = new CounterObj("JJJJJ");
        log.info("Step 1: Address: {} Value: {}", counterObj, counterObj.getValue());
        changeValueObj(counterObj);
        log.info("Step 3: Address: {} Value: {}", counterObj, counterObj.getValue());
    }

    private static void changeValueObj(CounterObj counterObj) {
        counterObj = new CounterObj("FFFFF");
        log.info("Step 2: Address: {} Value: {}", counterObj, counterObj.getValue());
    }
}
Truyền giá trị trong C++
Kết quả việc thay đổi giá trị đối tượng bằng cách khởi tạo đối tượng mới

Entrance the phase code on as after

  • Ở dòng 7, ta thực hiện khởi tạo đối tượng CounterObj, một đối tượng được lưu trong bộ nhớ Heap (giả sử nó có địa chỉ là 6996db8, giá trị của nó lúc này là JJJJJ), biến counterObj đồng thời được lưu trong một
  • Tại dòng 9, hàm changeValueObj() được gọi, lúc này biến counterObj được lưu trong khối ô nhớ của hàm changeValueObj() của Stack
  • Tại dòng 14, một đối tượng counterObj mới được tạo, được lưu trong Heap (có địa chỉ là 6504e3b2, giá trị là FFFFF), đồng thời biến counterObj được lưu trong khối ô nhớ của hàm changeValueObj() trong Stack
  • Ở dòng 10, ta in address and value of the object ban đầu, thì thấy nó không bị thay đổi giá trị, giá trị truyền vào hàm không bị tác động

Ví dụ 2. truyền đối tượng vào hàm, và thay đổi giá trị trong hàm bằng setter

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class Example {

    public static void main(String[] args) {
        CounterObj counterObj = new CounterObj("JJJJJ");
        log.info("Step 1: Address: {} Value: {}", counterObj, counterObj.getValue());
        changeValueObj(counterObj);
        log.info("Step 3: Address: {} Value: {}", counterObj, counterObj.getValue());
    }

    private static void changeValueObj(CounterObj counterObj) {
        counterObj.setValue("FFFFF");
        log.info("Step 2: Address: {} Value: {}", counterObj, counterObj.getValue());
    }
}
Truyền giá trị trong C++
Kết quả khi thực hiện thay đổi giá trị của đối tượng bằng setter

Entrance the phase code on as after

  • Ở dòng 7, ta thực hiện khởi tạo đối tượng CounterObj, một đối tượng được lưu trong bộ nhớ Heap (giả sử nó có địa chỉ là 6996db8, giá trị của nó lúc này là JJJJJ), biến counterObj đồng thời được lưu trong một
  • Tại dòng 9, hàm changeValueObj() được gọi, lúc này biến counterObj được lưu trong khối ô nhớ của hàm changeValueObj() của Stack
  • Ở dòng 13, ta truyền biến counterObj vào hàm, lúc này biến counterObj được sao chép thành một bản sao (có địa chỉ là 6996db8, giá trị của nó là JJJJJ)
  • Tại dòng 14, ta thực hiện thay đổi giá trị của giá trị thuộc tính, lúc này biến counterObj tham chiếu đến các đối tượng có địa chỉ 6996db8 trong Heap, nên giá trị của biến counterObj lúc này đã thay đổi ở cả trong hàm và bên ngoài hàm

3 – Trong java sử dụng truyền tham chiếu hay tham trị?

Từ các lập luận lập luận ở trên thì ta rút ra được rằng, trong java chỉ hỗ trợ truyền tham chiếu trị, không hỗ trợ truyền tham chiếu, không phải truyền nguyên thủy là tham trị còn truyền đối tượng là tham chiếu đâu nhé.