Không, nhưng có, nhưng có thể, nhưng có thể theo cách khác, nhưng không.
Như mọi người đã chỉ ra, (giả sử một ngôn ngữ trong đó phép cộng là liên kết trái, chẳng hạn như C, C ++, C # hoặc Java) thì biểu thức ((1 + 2) + 3)
hoàn toàn tương đương với 1 + 2 + 3
. Chúng là những cách khác nhau để viết một cái gì đó trong mã nguồn, điều đó sẽ không ảnh hưởng đến mã máy hoặc mã byte kết quả.
Dù bằng cách nào, kết quả sẽ là một hướng dẫn, ví dụ như thêm hai thanh ghi và sau đó thêm một thứ ba hoặc lấy hai giá trị từ một ngăn xếp, thêm nó, đẩy nó trở lại, sau đó lấy nó và một cái khác và thêm chúng, hoặc thêm ba thanh ghi vào một thao tác đơn lẻ hoặc một số cách khác để tính tổng ba số tùy thuộc vào mức nào hợp lý nhất ở cấp độ tiếp theo (mã máy hoặc mã byte). Trong trường hợp mã byte, đến lượt nó sẽ có khả năng tái cấu trúc tương tự trong đó, ví dụ như IL tương đương với điều này (sẽ là một loạt các tải cho một ngăn xếp và xuất hiện các cặp để thêm và sau đó đẩy lùi kết quả) sẽ không dẫn đến một bản sao trực tiếp của logic đó ở cấp mã máy, nhưng một cái gì đó hợp lý hơn cho máy đang đề cập.
Nhưng có một cái gì đó nhiều hơn cho câu hỏi của bạn.
Trong trường hợp của bất kỳ trình biên dịch C, C ++, Java hoặc C # lành mạnh nào, tôi đều mong đợi kết quả của cả hai câu lệnh bạn đưa ra đều có kết quả chính xác như sau:
int a = 6;
Tại sao mã kết quả phải lãng phí thời gian làm toán trên chữ? Không có thay đổi nào về trạng thái của chương trình sẽ ngăn chặn kết quả của 1 + 2 + 3
sự tồn tại 6
, vì vậy đó là những gì sẽ xảy ra trong mã đang được thực thi. Thật vậy, có lẽ thậm chí là không (tùy thuộc vào những gì bạn làm với 6 điều đó, có lẽ chúng ta có thể vứt bỏ toàn bộ; và thậm chí C # với triết lý "không tối ưu hóa nhiều, vì dù sao thì jitter cũng sẽ tối ưu hóa điều này" tương đương int a = 6
hoặc chỉ cần ném toàn bộ đi là không cần thiết).
Điều này mặc dù dẫn chúng tôi đến một phần mở rộng có thể của câu hỏi của bạn mặc dù. Hãy xem xét những điều sau đây:
int a = (b - 2) / 2;
/* or */
int a = (b / 2)--;
và
int c;
if(d < 100)
c = 0;
else
c = d * 31;
/* or */
int c = d < 100 ? 0 : d * 32 - d
/* or */
int c = d < 100 && d * 32 - d;
/* or */
int c = (d < 100) * (d * 32 - d);
(Lưu ý, hai ví dụ cuối cùng này không hợp lệ C #, trong khi mọi thứ khác ở đây là và chúng hợp lệ trong C, C ++ và Java.)
Ở đây một lần nữa, chúng tôi chính xác mã tương đương về đầu ra. Vì chúng không phải là biểu thức không đổi, chúng sẽ không được tính vào thời gian biên dịch. Có thể là một hình thức nhanh hơn một hình thức khác. Cái nào nhanh hơn? Điều đó phụ thuộc vào bộ xử lý và có lẽ vào một số khác biệt khá tùy tiện về trạng thái (đặc biệt là nếu nhanh hơn, nó không có khả năng nhanh hơn nhiều).
Và chúng không hoàn toàn không liên quan đến câu hỏi của bạn, vì chúng chủ yếu là về sự khác biệt theo thứ tự mà một cái gì đó được thực hiện về mặt khái niệm .
Trong mỗi người trong số họ, có một lý do để nghi ngờ rằng người này có thể nhanh hơn người kia. Các phân rã đơn có thể có một hướng dẫn chuyên biệt, vì vậy (b / 2)--
thực sự có thể nhanh hơn (b - 2) / 2
. d * 32
có lẽ có thể được sản xuất nhanh hơn bằng cách biến nó thành d << 5
quá d * 32 - d
nhanh hơn d * 31
. Sự khác biệt giữa hai cuối cùng là đặc biệt thú vị; một cho phép một số xử lý được bỏ qua trong một số trường hợp, nhưng cái khác tránh khả năng dự đoán sai nhánh.
Vì vậy, điều này khiến chúng ta có hai câu hỏi: 1. Cái này có thực sự nhanh hơn cái kia không? 2. Trình biên dịch sẽ chuyển đổi chậm hơn thành nhanh hơn?
Và câu trả lời là 1. Nó phụ thuộc. 2. Có thể.
Hoặc để mở rộng, nó phụ thuộc bởi vì nó phụ thuộc vào bộ xử lý được đề cập. Chắc chắn đã có các bộ xử lý tồn tại trong đó mã máy tương đương với mã này sẽ nhanh hơn mã máy tương đương với mã máy khác. Trong suốt lịch sử của điện toán điện tử, cũng không có cái nào luôn nhanh hơn cả (yếu tố dự đoán sai nhánh nói riêng không liên quan đến nhiều người khi CPU không có đường ống phổ biến hơn).
Và có thể, vì có một loạt các tối ưu hóa khác nhau mà trình biên dịch (và jitter, và script-engine) sẽ làm, và trong khi một số có thể được ủy quyền trong một số trường hợp nhất định, chúng ta thường có thể tìm thấy một số đoạn mã tương đương logic mà ngay cả trình biên dịch ngây thơ nhất cũng có kết quả chính xác và một số đoạn mã tương đương logic, trong đó ngay cả trình biên dịch phức tạp nhất cũng tạo ra mã nhanh hơn cho mã kia (ngay cả khi chúng ta phải viết một cái gì đó hoàn toàn bệnh hoạn chỉ để chứng minh quan điểm của chúng tôi).
Nó có vẻ như là một mối quan tâm tối ưu hóa rất nhỏ,
Không. Ngay cả với những khác biệt phức tạp hơn những gì tôi đưa ra ở đây, có vẻ như một mối quan tâm hoàn toàn trong vài phút không liên quan gì đến tối ưu hóa. Nếu bất cứ điều gì, đó là một vấn đề bi quan vì bạn nghi ngờ rằng khó đọc hơn ((1 + 2) + 3
có thể chậm hơn dễ đọc hơn 1 + 2 + 3
.
nhưng chọn C ++ trên C # / Java / ... tất cả là về tối ưu hóa (IMHO).
Nếu đó thực sự là việc chọn C ++ trên C # hoặc Java là "tất cả về" thì tôi nói mọi người nên ghi bản sao Stroustrup và ISO / IEC 14882 của họ và giải phóng không gian của trình biên dịch C ++ của họ để dành chỗ cho một số MP3 hoặc thứ gì đó.
Các ngôn ngữ này có lợi thế khác nhau so với nhau.
Một trong số đó là C ++ vẫn thường nhanh hơn và nhẹ hơn khi sử dụng bộ nhớ. Vâng, có những ví dụ trong đó C # và / hoặc Java nhanh hơn và / hoặc sử dụng bộ nhớ suốt đời ứng dụng tốt hơn và chúng trở nên phổ biến hơn khi các công nghệ liên quan cải thiện, nhưng chúng ta vẫn có thể mong đợi chương trình trung bình được viết bằng C ++ một tệp thực thi nhỏ hơn thực hiện công việc của nó nhanh hơn và sử dụng ít bộ nhớ hơn tương đương với một trong hai ngôn ngữ đó.
Đây không phải là tối ưu hóa.
Tối ưu hóa đôi khi được sử dụng để có nghĩa là "làm cho mọi thứ đi nhanh hơn". Điều đó có thể hiểu được, bởi vì thường khi chúng ta thực sự nói về "tối ưu hóa", chúng ta thực sự đang nói về việc làm cho mọi thứ trở nên nhanh hơn, và vì vậy người ta đã trở thành một người viết tắt cho người khác và tôi thừa nhận tôi đã sử dụng sai từ đó theo cách của mình.
Từ chính xác để "làm mọi thứ nhanh hơn" không phải là tối ưu hóa . Từ chính xác ở đây là cải tiến . Nếu bạn thực hiện một thay đổi cho một chương trình và sự khác biệt có ý nghĩa duy nhất là bây giờ nó nhanh hơn, nó không được tối ưu hóa theo bất kỳ cách nào, nó chỉ tốt hơn.
Tối ưu hóa là khi chúng tôi thực hiện một cải tiến liên quan đến một khía cạnh cụ thể và / hoặc trường hợp cụ thể. Ví dụ phổ biến là:
- Bây giờ nhanh hơn cho một trường hợp sử dụng, nhưng chậm hơn cho một trường hợp khác.
- Bây giờ nhanh hơn, nhưng sử dụng nhiều bộ nhớ hơn.
- Bây giờ nó nhẹ hơn về bộ nhớ, nhưng chậm hơn.
- Bây giờ nhanh hơn, nhưng khó bảo trì hơn.
- Bây giờ dễ dàng hơn để duy trì, nhưng chậm hơn.
Những trường hợp như vậy sẽ được biện minh nếu, ví dụ:
- Trường hợp sử dụng nhanh hơn là phổ biến hơn hoặc bị cản trở nghiêm trọng hơn để bắt đầu.
- Chương trình chậm đến mức không thể chấp nhận được và chúng tôi có rất nhiều RAM miễn phí.
- Chương trình bị đình trệ vì sử dụng quá nhiều RAM nên đã mất nhiều thời gian hơn so với thực hiện xử lý siêu nhanh.
- Chương trình chậm đến mức không thể chấp nhận được, và mã khó hiểu hơn được ghi lại tốt và tương đối ổn định.
- Chương trình vẫn nhanh chóng chấp nhận được và cơ sở mã dễ hiểu hơn rẻ hơn để duy trì và cho phép các cải tiến khác được thực hiện dễ dàng hơn.
Nhưng, những trường hợp như vậy cũng sẽ không được chứng minh trong các tình huống khác: Mã không được cải thiện bằng một thước đo chất lượng không thể sai lầm tuyệt đối, nó được làm tốt hơn trong một khía cạnh cụ thể giúp nó phù hợp hơn cho việc sử dụng cụ thể; tối ưu hóa.
Và sự lựa chọn ngôn ngữ có ảnh hưởng ở đây, bởi vì tốc độ, việc sử dụng bộ nhớ và khả năng đọc đều có thể bị ảnh hưởng bởi nó, nhưng vì vậy có thể tương thích với các hệ thống khác, tính sẵn có của thư viện, thời gian chạy, sự trưởng thành của các thời gian chạy trên một hệ điều hành nhất định (vì tội lỗi của tôi, bằng cách nào đó tôi đã kết thúc việc có Linux và Android là hệ điều hành yêu thích và C # là ngôn ngữ yêu thích của tôi, và trong khi Mono thì tuyệt vời, nhưng tôi vẫn gặp phải vấn đề này khá nhiều).
Nói "chọn C ++ trên C # / Java / ... là tất cả về tối ưu hóa" chỉ có ý nghĩa nếu bạn nghĩ C ++ thực sự hấp dẫn, bởi vì tối ưu hóa là về "tốt hơn mặc dù ..." không "tốt hơn". Nếu bạn nghĩ rằng C ++ tốt hơn bất chấp chính nó, thì điều cuối cùng bạn cần là lo lắng về những phút cực nhỏ có thể xảy ra. Thật vậy, có lẽ bạn tốt hơn hết nên từ bỏ nó; tin tặc hạnh phúc là một chất lượng để tối ưu hóa quá!
Tuy nhiên, nếu bạn có xu hướng nói "Tôi yêu C ++ và một trong những điều tôi yêu thích về nó là vắt kiệt thêm chu kỳ", thì đó lại là một vấn đề khác. Vẫn còn một trường hợp rằng các vi lệnh chỉ có giá trị nếu chúng có thể là một thói quen phản xạ (nghĩa là cách bạn có xu hướng mã hóa tự nhiên sẽ nhanh hơn thường xuyên hơn là chậm hơn). Mặt khác, chúng thậm chí không được tối ưu hóa sớm, chúng là sự bi quan sớm khiến mọi thứ trở nên tồi tệ hơn.