Tính chính xác của mã bạn viết không bao giờ nên phụ thuộc vào tối ưu hóa. Nó sẽ xuất kết quả chính xác khi được thực thi trên "máy ảo" C ++ mà họ sử dụng trong đặc tả.
Tuy nhiên, những gì bạn nói về nhiều hơn là một loại câu hỏi hiệu quả. Mã của bạn chạy tốt hơn nếu được tối ưu hóa với trình biên dịch tối ưu hóa RVO. Điều đó tốt, vì tất cả các lý do đã chỉ ra trong các câu trả lời khác.
Tuy nhiên, nếu bạn yêu cầu tối ưu hóa này (chẳng hạn như nếu trình xây dựng sao chép thực sự sẽ khiến mã của bạn bị lỗi), thì bây giờ bạn đang ở trạng thái bất chợt của trình biên dịch.
Tôi nghĩ rằng ví dụ tốt nhất về điều này trong thực tế của riêng tôi là tối ưu hóa cuộc gọi đuôi:
int sillyAdd(int a, int b)
{
if (b == 0)
return a;
return sillyAdd(a + 1, b - 1);
}
Đó là một ví dụ ngớ ngẩn, nhưng nó hiển thị một lệnh gọi đuôi, trong đó một hàm được gọi đệ quy ngay ở cuối hàm. Máy ảo C ++ sẽ chỉ ra rằng mã này hoạt động đúng, mặc dù tôi có thể gây ra một chút nhầm lẫn về lý do tại sao tôi lại bận tâm viết một thói quen bổ sung như vậy ngay từ đầu. Tuy nhiên, trong các triển khai thực tế của C ++, chúng tôi có một ngăn xếp và nó có không gian hạn chế. Nếu được thực hiện theo phương pháp sư phạm, chức năng này sẽ phải đẩy ít nhất b + 1
các khung xếp chồng lên ngăn xếp khi nó bổ sung. Nếu tôi muốn tính toán sillyAdd(5, 7)
, đây không phải là một vấn đề lớn. Nếu tôi muốn tính toán sillyAdd(0, 1000000000)
, tôi có thể gặp rắc rối thực sự khi tạo ra StackOverflow (và không phải là loại tốt ).
Tuy nhiên, chúng ta có thể thấy rằng một khi chúng ta đạt đến dòng trả về cuối cùng đó, chúng ta thực sự đã hoàn thành mọi thứ trong khung stack hiện tại. Chúng tôi không thực sự cần phải giữ nó xung quanh. Tối ưu hóa cuộc gọi đuôi cho phép bạn "tái sử dụng" khung ngăn xếp hiện có cho chức năng tiếp theo. Theo cách này, chúng ta chỉ cần 1 khung stack, chứ không phải b+1
. (Chúng ta vẫn phải thực hiện tất cả các phép cộng và phép trừ ngớ ngẩn đó, nhưng chúng không chiếm nhiều dung lượng hơn.) Thực tế, việc tối ưu hóa biến mã thành:
int sillyAdd(int a, int b)
{
begin:
if (b == 0)
return a;
// return sillyAdd(a + 1, b - 1);
a = a + 1;
b = b - 1;
goto begin;
}
Trong một số ngôn ngữ, tối ưu hóa cuộc gọi đuôi được yêu cầu rõ ràng theo thông số kỹ thuật. C ++ không phải là một trong số đó. Tôi không thể dựa vào trình biên dịch C ++ để nhận ra cơ hội tối ưu hóa cuộc gọi đuôi này, trừ khi tôi đi từng trường hợp cụ thể. Với phiên bản Visual Studio của tôi, phiên bản phát hành thực hiện tối ưu hóa cuộc gọi đuôi, nhưng phiên bản gỡ lỗi thì không (theo thiết kế).
Do đó, sẽ rất tệ cho tôi khi phụ thuộc vào khả năng tính toán sillyAdd(0, 1000000000)
.