Có một số khác biệt trong cách gọi các quy ước trong C ++ và Java. Trong C ++, về mặt kỹ thuật chỉ có hai quy ước: pass-by-value và pass-by-Reference, với một số tài liệu bao gồm quy ước truyền qua con trỏ thứ ba (đó thực sự là giá trị truyền của loại con trỏ). Trên hết, bạn có thể thêm const-ness vào loại đối số, nâng cao ngữ nghĩa.
Đi qua tham khảo
Chuyển qua tham chiếu có nghĩa là hàm sẽ nhận được khái niệm đối tượng của bạn và không phải là bản sao của nó. Tham chiếu về mặt khái niệm là bí danh cho đối tượng được sử dụng trong ngữ cảnh gọi và không thể là null. Tất cả các hoạt động được thực hiện bên trong chức năng áp dụng cho đối tượng bên ngoài chức năng. Quy ước này không có sẵn trong Java hoặc C.
Truyền theo giá trị (và truyền qua con trỏ)
Trình biên dịch sẽ tạo một bản sao của đối tượng trong ngữ cảnh gọi và sử dụng bản sao đó bên trong hàm. Tất cả các hoạt động được thực hiện bên trong chức năng được thực hiện để sao chép, không phải phần tử bên ngoài. Đây là quy ước cho các kiểu nguyên thủy trong Java.
Một phiên bản đặc biệt của nó là chuyển một con trỏ (địa chỉ - của đối tượng) vào một hàm. Hàm nhận con trỏ, và bất kỳ và tất cả các hoạt động được áp dụng cho chính con trỏ đều được áp dụng cho bản sao (con trỏ), mặt khác, các hoạt động được áp dụng cho con trỏ bị hủy đăng ký sẽ áp dụng cho thể hiện đối tượng tại vị trí bộ nhớ đó, do đó hàm có thể có tác dụng phụ. Hiệu quả của việc sử dụng giá trị truyền của con trỏ tới đối tượng sẽ cho phép hàm bên trong sửa đổi giá trị bên ngoài, như với tham chiếu qua và cũng sẽ cho phép các giá trị tùy chọn (truyền con trỏ null).
Đây là quy ước được sử dụng trong C khi một hàm cần sửa đổi một biến ngoài và quy ước được sử dụng trong Java với các kiểu tham chiếu: tham chiếu được sao chép, nhưng đối tượng được tham chiếu giống nhau: các thay đổi đối với tham chiếu / con trỏ không hiển thị bên ngoài chức năng, nhưng thay đổi bộ nhớ nhọn là.
Thêm const vào phương trình
Trong C ++, bạn có thể gán hằng số cho các đối tượng khi xác định các biến, con trỏ và tham chiếu ở các mức khác nhau. Bạn có thể khai báo một biến là hằng số, bạn có thể khai báo một tham chiếu đến một thể hiện hằng và bạn có thể định nghĩa tất cả các con trỏ tới các đối tượng không đổi, các con trỏ không đổi cho các đối tượng có thể thay đổi và các con trỏ không đổi thành các phần tử không đổi. Ngược lại, trong Java, bạn chỉ có thể định nghĩa một mức không đổi (từ khóa cuối cùng): đó là biến số (ví dụ cho các kiểu nguyên thủy, tham chiếu cho các kiểu tham chiếu), nhưng bạn không thể định nghĩa một tham chiếu đến một phần tử bất biến (trừ khi chính lớp đó là bất biến).
Điều này được sử dụng rộng rãi trong các quy ước gọi C ++. Khi các đối tượng nhỏ, bạn có thể truyền đối tượng theo giá trị. Trình biên dịch sẽ tạo ra một bản sao, nhưng bản sao đó không phải là một hoạt động đắt tiền. Đối với bất kỳ loại nào khác, nếu hàm sẽ không thay đổi đối tượng, bạn có thể chuyển tham chiếu đến một thể hiện không đổi (thường được gọi là tham chiếu không đổi) của loại. Điều này sẽ không sao chép đối tượng, nhưng chuyển nó vào hàm. Nhưng đồng thời trình biên dịch sẽ đảm bảo rằng đối tượng không bị thay đổi bên trong hàm.
Quy tắc của ngón tay cái
Đây là một số quy tắc cơ bản cần tuân theo:
- Thích pass-by-value cho các kiểu nguyên thủy
- Thích tham chiếu qua với tham chiếu đến hằng số cho các loại khác
- Nếu hàm cần sửa đổi đối số, hãy sử dụng tham chiếu qua
- Nếu đối số là tùy chọn, hãy sử dụng con trỏ qua (thành hằng nếu giá trị tùy chọn không được sửa đổi)
Có những sai lệch nhỏ khác so với các quy tắc này, đầu tiên là xử lý quyền sở hữu đối tượng. Khi một đối tượng được phân bổ động với mới, nó phải được giải quyết bằng cách xóa (hoặc các phiên bản [] của chúng). Đối tượng hoặc chức năng chịu trách nhiệm cho việc phá hủy đối tượng được coi là chủ sở hữu của tài nguyên. Khi một đối tượng được phân bổ động được tạo trong một đoạn mã, nhưng quyền sở hữu được chuyển sang một phần tử khác, nó thường được thực hiện với ngữ nghĩa của con trỏ hoặc nếu có thể với con trỏ thông minh.
Lưu ý bên
Điều quan trọng là nhấn mạnh tầm quan trọng của sự khác biệt giữa các tham chiếu C ++ và Java. Trong các tham chiếu C ++ về mặt khái niệm là ví dụ của đối tượng, không phải là một trình truy cập vào nó. Ví dụ đơn giản nhất là thực hiện chức năng hoán đổi:
// C++
class Type; // defined somewhere before, with the appropriate operations
void swap( Type & a, Type & b ) {
Type tmp = a;
a = b;
b = tmp;
}
int main() {
Type a, b;
Type old_a = a, old_b = b;
swap( a, b );
assert( a == old_b );
assert( b == old_a );
}
Hàm hoán đổi ở trên thay đổi cả hai đối số của nó thông qua việc sử dụng các tham chiếu. Mã gần nhất trong Java:
public class C {
// ...
public static void swap( C a, C b ) {
C tmp = a;
a = b;
b = tmp;
}
public static void main( String args[] ) {
C a = new C();
C b = new C();
C old_a = a;
C old_b = b;
swap( a, b );
// a and b remain unchanged a==old_a, and b==old_b
}
}
Phiên bản Java của mã sẽ sửa đổi các bản sao của các tham chiếu bên trong, nhưng sẽ không sửa đổi các đối tượng thực tế bên ngoài. Tham chiếu Java là con trỏ C không có số học con trỏ được truyền theo giá trị vào các hàm.