Nội dung chính
1. Các biến số tăng và giảm
Tăng (thêm 1 vào) và giảm (trừ 1 với) nó phổ biến đến mức chúng có các toán tử riêng.
Toán tử | ký hiệu | Form | Mô tả |
Tăng tiền tố (tăng trước) | ++ | ++x | Tăng x, sau đó trả về x |
Giảm tiền tố (giảm trước) | –– | ––x | Giảm x, sau đó trả về x |
Gia số hậu tố (tăng hậu tố) | ++ | x++ | Sao chép x, sau đó tăng x, sau đó trả lại bản sao |
Postfix giảm (sau giảm) | –– | x–– | Sao chép x, sau đó giảm x, sau đó trả lại bản sao |
Lưu ý rằng có hai phiên bản của mỗi toán tử – phiên bản tiền tố (trong đó toán tử đứng trước toán hạng) và phiên bản hậu tố (trong đó toán tử đứng sau toán hạng).
Các toán tử tăng / giảm tiền tố rất đơn giản. Đầu tiên, toán hạng được tăng hoặc giảm, và sau đó biểu thức đánh giá giá trị của toán hạng. Ví dụ:
#include <iostream>
int main()
{
int x { 5 };
int y = ++x; // x is incremented to 6, x is evaluated to the value 6, and 6 is assigned to y
std::cout << x << ' ' << y;
return 0;
}
print:
6 6
Các toán tử tăng / giảm hậu tố phức tạp hơn. Đầu tiên, một bản sao của toán hạng được tạo. Sau đó, toán hạng (không phải bản sao) được tăng hoặc giảm. Cuối cùng, bản sao (không phải bản gốc) mới được đánh giá. Ví dụ:
#include <iostream>
int main()
{
int x { 5 };
int y = x++; // x is incremented to 6, copy of original x is evaluated to the value 5, and 5 is assigned to y
std::cout << x << ' ' << y;
return 0;
}
print:
6 5
Hãy xem xét cách thức hoạt động của dòng 6 này chi tiết hơn. Đầu tiên, một bản sao tạm thời của x được tạo bắt đầu với cùng giá trị với x (5). Sau đó, x thực tế được tăng từ 5 lên 6. Sau đó, bản sao của x (vẫn có giá trị 5) được trả về và gán cho y. Sau đó, bản sao tạm thời bị loại bỏ.
Do đó, y kết thúc bằng giá trị 5 (giá trị tăng trước) và x kết thúc bằng giá trị 6 (giá trị tăng sau).
Lưu ý rằng phiên bản tiền tố thực hiện nhiều bước hơn và do đó có thể không hiệu quả như phiên bản tiền tố.
Đây là một ví dụ khác cho thấy sự khác biệt giữa các phiên bản tiền tố và hậu tố:
/*
Cafedev.vn - Kênh thông tin IT hàng đầu Việt Nam
@author cafedevn
Contact: cafedevn@gmail.com
Fanpage: https://www.facebook.com/cafedevn
Group: https://www.facebook.com/groups/cafedev.vn/
Instagram: https://instagram.com/cafedevn
Twitter: https://twitter.com/CafedeVn
Linkedin: https://www.linkedin.com/in/cafe-dev-407054199/
Pinterest: https://www.pinterest.com/cafedevvn/
YouTube: https://www.youtube.com/channel/UCE7zpY_SlHGEgo67pHxqIoA/
*/
#include <iostream>
int main()
{
int x{ 5 };
int y{ 5 };
std::cout << x << ' ' << y << '\n';
std::cout << ++x << ' ' << --y << '\n'; // prefix
std::cout << x << ' ' << y << '\n';
std::cout << x++ << ' ' << y-- << '\n'; // postfix
std::cout << x << ' ' << y << '\n';
return 0;
}
print:
5 5
6 4
6 4
6 4
7 3
Trên dòng thứ 8, chúng ta thực hiện tăng và giảm tiền tố. Trên dòng này, x và y được tăng / giảm trước khi giá trị của chúng được gửi đến std :: cout, vì vậy chúng ta thấy các giá trị cập nhật của chúng được phản ánh bởi std :: cout.
Trên dòng thứ 10, chúng ta thực hiện tăng và giảm hậu tố. Trên dòng này, bản sao của x và y (với các giá trị tăng trước và giảm trước) là những gì được gửi đến std :: cout, vì vậy chúng ta không thấy mức tăng và giảm được phản ánh ở đây. Những thay đổi đó không hiển thị cho đến dòng tiếp theo, khi x và y được đánh giá lại.
Bạn nên: Đặc biệt ủng hộ phiên bản tiền tố của toán tử tăng và giảm, vì chúng thường hoạt động tốt hơn và bạn ít có khả năng gặp phải các vấn đề lạ với chúng.
2. Vấn đề phụ
Một hàm hoặc biểu thức được cho là có tác dụng phụ nếu nó thực hiện bất cứ điều gì tồn tại ngoài vòng đời của chính hàm hoặc biểu thức.
Các ví dụ phổ biến về tác dụng phụ bao gồm thay đổi giá trị của đối tượng, thực hiện nhập hoặc xuất hoặc cập nhật giao diện người dùng đồ họa (ví dụ: bật hoặc tắt một nút).
Hầu hết thời gian, tác dụng phụ là hữu ích:
x = 5; // the assignment operator modifies the state of x
++x; // operator++ modifies the state of x
std::cout << x; // operator<< modifies the state of the console
Toán tử gán trong ví dụ trên có tác dụng phụ là thay đổi giá trị của x vĩnh viễn. Ngay cả sau khi câu lệnh kết thúc thực thi, x vẫn sẽ có giá trị 5. Tương tự với toán tử ++, giá trị của x bị thay đổi ngay cả khi câu lệnh đã kết thúc đánh giá. Việc xuất ra x cũng có tác dụng phụ là sửa đổi trạng thái của bảng điều khiển, vì bây giờ bạn có thể thấy giá trị của x được in vào console.
Tuy nhiên, các tác dụng phụ cũng có thể dẫn đến kết quả không mong muốn:
int add(int x, int y)
{
return x + y;
}
int main()
{
int x{ 5 };
int value = add(x, ++x); // is this 5 + 6, or 6 + 6?
// It depends on what order your compiler evaluates the function arguments in
std::cout << value; // value could be 11 or 12, depending on how the above line evaluates!
return 0;
}
C ++ không xác định thứ tự mà các đối số hàm được đánh giá. Nếu đối số bên trái được đánh giá đầu tiên, điều này sẽ trở thành lệnh gọi thêm (5, 6), bằng 11. Nếu đối số bên phải được đánh giá trước, điều này sẽ trở thành lệnh gọi thêm (6, 6), bằng 12! Lưu ý rằng đây chỉ là một vấn đề vì một trong các đối số của hàm add () có tác dụng phụ.
Có những trường hợp khác trong đó C ++ không chỉ định thứ tự mà một số thứ nhất định được đánh giá (chẳng hạn như toán hạng của toán tử), vì vậy các trình biên dịch khác nhau có thể thể hiện các hành vi khác nhau. Ngay cả khi C ++ làm rõ ràng mọi thứ nên được đánh giá như thế nào, thì về mặt lịch sử, đây là một lĩnh vực có rất nhiều lỗi trình biên dịch. Tất cả những vấn đề này thường có thể tránh được bằng cách đảm bảo rằng bất kỳ biến nào có tác dụng phụ được áp dụng đều được sử dụng không quá một lần trong một câu lệnh nhất định.
Lưu ý: C ++ không xác định thứ tự đánh giá cho các đối số hàm hoặc toán hạng toán tử.
Bạn nên: Không sử dụng một biến có tác dụng phụ áp dụng cho nó nhiều lần trong một câu lệnh nhất định. Nếu bạn làm vậy, kết quả có thể không được xác định.
Cài ứng dụng cafedev để dễ dàng cập nhật tin và học lập trình mọi lúc mọi nơi tại đây.
Nguồn và Tài liệu tiếng anh tham khảo:
Tài liệu từ cafedev:
- Full series tự học C++ từ cơ bản tới nâng cao tại đây nha.
- Ebook về C++ tại đây.
- Các series tự học lập trình MIỄN PHÍ khác
- Nơi liên hệ hợp tác hoặc quảng cáo cùng Cafedevn tại đây.
Nếu bạn thấy hay và hữu ích, bạn có thể tham gia các kênh sau của cafedev để nhận được nhiều hơn nữa:
Chào thân ái và quyết thắng!