Bạn có thể chuyển một đối tượng theo giá trị trong C++ không?

C++ là một ví dụ về ngôn ngữ mô hình truyền thông báo, có nghĩa là các đối tượng và giá trị được truyền cho các hàm, sau đó trả về các đối tượng và giá trị khác dựa trên dữ liệu đầu vào. Một trong những lợi ích của C++ là nó cho phép kiểm soát rất chi tiết đối với các giao diện chức năng này, cũng như cách các đối tượng được truyền được lưu trữ và thao tác. Trong bài viết này, tôi sẽ thảo luận về các phương pháp truyền dữ liệu/đối tượng khác nhau cho một hàm và điều này sẽ ảnh hưởng như thế nào đến hiệu quả và hoạt động của các thuật toán lượng tử của bạn

Trong C++ có ba cách khác nhau để truyền dữ liệu cho một hàm. Chúng tương ứng theo giá trị, theo tham chiếu và theo con trỏ. Tất cả đều có những đặc điểm khác nhau khi nói đến hiệu quả, lưu trữ và hành vi. Chúng tôi sẽ không tập trung vào phương thức thứ hai, truyền qua con trỏ, vì nó là phương thức kế thừa được sử dụng bởi các chương trình kiểu C (cũng như con trỏ hàm). Thay vào đó, chúng tôi sẽ tập trung vào phương pháp thứ nhất và thứ hai

Vượt qua giá trị

Khi một đối tượng (hoặc kiểu dựng sẵn) được truyền theo giá trị cho một hàm, thì đối tượng bên dưới sẽ được sao chép bằng cách sử dụng hàm tạo sao chép của nó. Đối tượng mới có bộ nhớ bổ sung được phân bổ cho nó và tất cả các giá trị cũng như đối tượng con được sao chép và lưu trữ riêng. Nếu đối tượng được truyền là loại tích hợp sẵn, chẳng hạn như giá trị int hoặc double thì quá trình sao chép sẽ rẻ và thường sẽ không ảnh hưởng đến hiệu suất. Tuy nhiên, nếu đối tượng được truyền chứa nhiều giá trị được lưu trữ, chẳng hạn như vectơ hoặc ma trận thì quá trình sao chép sẽ tốn kém cả về lưu trữ và chu kỳ CPU

Truyền một đối tượng theo giá trị cũng có nghĩa là bất kỳ sửa đổi nào được thực hiện đối với đối tượng, trong phạm vi của hàm được truyền đối tượng, sẽ xảy ra trên đối tượng được sao chép chứ không phải trên đối tượng đã được truyền. Điều này gây nhầm lẫn cho những người mới bắt đầu lập trình C++ cũng như là nguồn phát sinh lỗi

Thí dụ. Xem xét một hàm định mức tính toán định mức Euclide của một vectơ có giá trị kép. Hàm trả về một giá trị chính xác kép ("chuẩn") và lấy vectơ làm tham số. Đoạn mã sau cho thấy vectơ được truyền theo giá trị

double euclid_norm(vector my_vector);

Điều này sẽ sao chép vectơ và sẽ thực hiện bất kỳ thay đổi cơ bản nào đối với bản sao của vectơ đó, thay vì chính vectơ đó. Hàm định mức không được sửa đổi vectơ, chỉ đọc dữ liệu của nó. Việc triển khai này không lý tưởng. Nó đắt tiền và giao diện không ngụ ý cách sử dụng chính xác

Đi qua tham khảo

Khi một đối tượng (hoặc kiểu dựng sẵn) được chuyển qua tham chiếu đến một hàm, đối tượng bên dưới sẽ không được sao chép. Hàm được cung cấp địa chỉ bộ nhớ của chính đối tượng. Điều này giúp tiết kiệm cả bộ nhớ và chu kỳ CPU vì không có bộ nhớ mới nào được cấp phát và không có hàm tạo bản sao (đắt tiền) nào được gọi. Đó là một hoạt động hiệu quả hơn nhiều

Nếu hàm được truyền đối tượng bây giờ sửa đổi đối tượng theo bất kỳ cách nào, thì đối tượng ban đầu sẽ phản ánh những sửa đổi đó, thay vì một bản sao của đối tượng. Trong một số trường hợp, đây chính xác là những gì được dự định. Trong các tình huống khác, đây có thể không phải là hành vi mong muốn. Một lần nữa có khả năng xảy ra lỗi. Cụ thể, hàm định mức vectơ như được mô tả ở trên sẽ không thể sửa đổi đối tượng vectơ đã truyền

Đây là hàm euclid_norm tương tự được sửa đổi để chuyển vectơ theo tham chiếu. Lưu ý ký hiệu tham chiếu được thêm vào (&)

double euclid_norm(vector& my_vector);

Chuyển qua tham chiếu đến Const

Để giải quyết vấn đề không sao chép VÀ không sửa đổi dữ liệu cơ bản, một kỹ thuật được gọi là chuyển tham chiếu đến const được sử dụng. Điều này tương tự như chuyển qua tham chiếu ngoại trừ việc chúng tôi đánh dấu tham số my_vector là đối tượng

double euclid_norm(vector& my_vector);
0. Điều này yêu cầu euclid_norm không sửa đổi my_vector trong phạm vi của chính nó

double euclid_norm(const vector& my_vector);

Giao diện của chúng tôi bây giờ chính xác hơn nhiều về mục đích của nó. Từ khóa

double euclid_norm(vector& my_vector);
0 đánh dấu my_vector là không thể sửa đổi, trong khi ký hiệu tham chiếu (&) nói rằng nó không nên được sao chép. Đây chính xác là hành vi mà chúng ta muốn từ một chức năng định mức

Gần như tất cả các trường hợp của các hàm "chỉ đọc" toán học phải được thêm tiền tố theo cách này. Giao diện máy khách không chỉ rõ ràng hơn mà còn có hiệu quả cao và sẽ không gây ra lỗi ghi đè dữ liệu. Ngoại lệ duy nhất cho điều này là khi chuyển các loại tích hợp. Việc sao chép dữ liệu như vậy là không tốn kém và do đó bạn có thể chỉ cần chuyển theo giá trị

Truyền tham chiếu có nghĩa là chuyển tham chiếu của một đối số trong hàm gọi đến tham số hình thức tương ứng của hàm được gọi. Hàm được gọi có thể sửa đổi giá trị của đối số bằng cách sử dụng tham chiếu của nó được truyền vào

Ví dụ sau đây cho thấy cách các đối số được truyền bằng tham chiếu. Các tham số tham chiếu được khởi tạo với các đối số thực khi hàm được gọi

CCNX06A

#include 

void swapnum(int &i, int &j) {
  int temp = i;
  i = j;
  j = temp;
}

int main(void) {
  int a = 10;
  int b = 20;

  swapnum(a, b);
  printf("A is %d and B is %d\n", a, b);
  return 0;
}

Khi hàm

double euclid_norm(vector& my_vector);
5 được gọi, giá trị của biến
double euclid_norm(vector& my_vector);
6 và
double euclid_norm(vector& my_vector);
7 được hoán đổi vì chúng được truyền theo tham chiếu. đầu ra là.
A is 20 and B is 10

Để sửa đổi một tham chiếu đủ điều kiện bởi từ hạn định

double euclid_norm(vector& my_vector);
0, bạn phải loại bỏ hằng số của nó bằng toán tử
double euclid_norm(vector& my_vector);
9. Ví dụ.
#include 
using namespace std;

void f(const int& x) {
  int& y = const_cast(x);
  ++y;
}

int main() {
  int a = 5;
  f(a);
  cout << a << endl;
}
Ví dụ này xuất ra
double euclid_norm(const vector& my_vector);
0

Truyền theo tham chiếu hiệu quả hơn truyền theo giá trị, vì nó không sao chép các đối số. Tham số chính thức là bí danh cho đối số. Khi hàm được gọi đọc hoặc ghi tham số hình thức, nó thực sự đọc hoặc ghi chính đối số đó

Sự khác biệt giữa truyền theo tham chiếu và truyền theo con trỏ là con trỏ có thể được

double euclid_norm(const vector& my_vector);
1 hoặc gán lại trong khi tham chiếu không thể. Sử dụng chuyển từng con trỏ nếu
double euclid_norm(const vector& my_vector);
1 là một giá trị tham số hợp lệ hoặc nếu bạn muốn gán lại con trỏ. Nếu không, hãy sử dụng các tham chiếu không đổi hoặc không cố định để truyền đối số

Bạn có thể chuyển một đối tượng theo giá trị không?

Giá trị của một đối tượng có thể thay đổi có thể được thay đổi khi nó được truyền vào một phương thức. Không thể thay đổi giá trị của đối tượng bất biến, ngay cả khi nó được truyền một giá trị mới. “Truyền theo giá trị” có nghĩa là chuyển một bản sao của giá trị . "Truyền theo tham chiếu" đề cập đến việc chuyển tham chiếu thực của biến trong bộ nhớ.

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 .

Các đối tượng có thể được truyền theo giá trị trong C++ không?

Truyền theo giá trị . Đối tượng mới có bộ nhớ bổ sung được phân bổ cho nó và tất cả các giá trị cũng như đối tượng con được sao chép và lưu trữ riêng. When an object (or built-in type) is passed by value to a function, the underlying object is copied using its copy constructor. The new object has additional memory allocated to it and all values and sub-objects are copied and stored separately.

Bạn có thể chuyển qua tham chiếu trong C không?

Truyền tham chiếu đề cập đến một phương thức truyền địa chỉ của một đối số trong hàm gọi đến một tham số tương ứng trong hàm được gọi. Trong C, tham số tương ứng trong hàm được gọi phải được khai báo là kiểu con trỏ