2010-01-23 23 views
8

chương trình này:Tại sao endl được sử dụng như một từ đồng nghĩa cho " n" mặc dù nó bị phạt nặng?

#include <iostream> 
#include <cstdlib> 
#include <string> 

int main(int argc, const char *argv[]) 
{ 
    using ::std::cerr; 
    using ::std::cout; 
    using ::std::endl; 

    if (argc < 2 || argc > 3) { 
     cerr << "Usage: " << argv[0] << " [<count>] <message>\n"; 
     return 1; 
    } 
    unsigned long count = 10000; 
    if (argc > 2) { 
     char *endptr = 0; 
     count = ::std::strtoul(argv[1], &endptr, 10); 
     if ((argv[1][0] == '\0') || (*endptr != '\0')) { 
     cerr << "Usage: " << argv[0] << " [<count>] <message>\n"; 
     return 1; 
     } 
    } 
    const ::std::string msg((argc < 3) ? argv[1] : argv[2]); 
    for (unsigned long i = 0; i < count; ++i) { 
     cout << i << ": " << msg << '\n'; 
    } 
    return 0; 
} 

khi đúng lúc như vậy:

$ time ./joe 10000000 fred >/dev/null 

real 0m15.410s 
user 0m10.551s 
sys 0m0.166s 

mất 15,4 giây của thời gian thực để thực thi. Thay thế dòng đầu ra với điều này: cout << i << ": " << msg << endl; và bạn kết thúc với một cái gì đó như thế này:

$ time ./joe 10000000 fred >/dev/null 

real 0m39.115s 
user 0m16.482s 
sys 0m15.803s 

Như bạn có thể thấy, thời gian để chạy hơn gấp đôi, và chương trình đi từ dành thời gian tối thiểu trong hệ điều hành để chi tiêu gần một nửa thời gian trong hệ điều hành.

Cả hai phiên bản của chương trình đều có đầu ra giống nhau và được đảm bảo theo tiêu chuẩn để có kết quả giống nhau trên mọi nền tảng.

Vì điều này, tại sao mọi người kiên trì trong việc sử dụng endl như một từ đồng nghĩa với '\n'?

Edit: Trong trường hợp nó không phải là rõ ràng, câu hỏi này được thiết kế để trở thành một câu hỏi hàng đầu và là ở đây cho mục đích giảng dạy . Tôi biết lý do tại sao các hình phạt hiệu suất tồn tại.

+0

Bạn có thể cho tôi biết phần nào của tiêu chuẩn đảm bảo rằng đầu ra sẽ giống nhau trên tất cả các nền tảng không? – Glen

+2

Xem: http://stackoverflow.com/questions/213907/c-stdendl-vs-n –

Trả lời

21

Tôi không chắc chắn. Chèn std::endl vào luồng đầu ra được định nghĩa là tương đương với việc chèn .widen('\n') và sau đó gọi flush() và nhiều lập trình viên vẫn tồn tại trong việc sử dụng std::endl ngay cả khi không có nguyên nhân để tuôn ra, ví dụ như chúng tiếp tục xuất ngay lập tức.

Giả định của tôi là nó đến từ một niềm tin không chính xác rằng nó bằng cách nào đó là di động hơn bởi vì nó không sử dụng rõ ràng một ký tự dòng mới cụ thể. Điều này không chính xác vì \n phải luôn được ánh xạ tới trình tự dòng mới chính xác của hệ thống đối với các tệp không phải nhị phân theo thư viện luồng.

+2

Bạn biết đấy, bạn là người đầu tiên đưa ra câu trả lời thực tế. :-) Đặt câu hỏi hàng đầu sẽ đưa bạn đến đâu đó trên trang web này. Tôi cần phải tìm một cách tốt hơn để nêu rõ các câu hỏi mà tôi định hướng dẫn. – Omnifarious

+0

Tôi đã đưa ra một câu trả lời thực tế quá, vì nó xảy ra. Bạn có thể không đồng ý với nó, tất nhiên. –

+0

@Neil Butterworth, Ồ, được rồi. Vâng, Charles là người thứ hai đưa ra câu trả lời thực tế. :-) Của bạn là quá. – Omnifarious

0

Câu hỏi thực sự là, tại sao trình biên dịch lại tạo ra một con chó ăn sáng để biên soạn phiên bản endl? Nếu họ được đảm bảo có cùng ngữ nghĩa, thì họ cũng nên có cùng thời gian chạy.

Chỉnh sửa: rõ ràng là tôi đã không biết rằng endl đã xóa luồng ... đó là những gì bạn nhận được khi không tìm kiếm.

+2

Chúng không được đảm bảo có cùng ngữ nghĩa. –

+0

Trên thực tế, hầu hết chúng không có cùng ngữ nghĩa. – Omnifarious

+0

Vâng, họ có thể làm, họ chỉ không được đảm bảo bởi tiêu chuẩn C++. –

4

Không phải ai cũng quan tâm nhiều đến hiệu suất. Đối với một số ứng dụng, đảm bảo luồng được xả đỏ là quan trọng hơn nhiều.

Edit: Ngoài ra, tôi tìm endl dễ gõ hơn '\n' :-)

+0

Trong hầu như không có trường hợp mà tôi nhìn thấy 'endl' được sử dụng hiện nó thực sự quan trọng nếu dòng là đỏ bừng ngay sau đó và ở đó. :-) – Omnifarious

+0

Ghi nhật ký các ứng dụng, thông tin liên lạc và cơ sở dữ liệu mạng ngay lập tức. –

+0

Mọi người nên sử dụng ':: std :: cerr' hoặc một số luồng không bị chặn khác để ghi nhật ký. Tôi chưa bao giờ thấy một ứng dụng mạng hoặc cơ sở dữ liệu nghiêm trọng nào sử dụng iostream để liên lạc qua mạng hoặc ghi vào cơ sở dữ liệu. – Omnifarious

4

Afaik, endl cũng xả suối, có thể là nguyên nhân của hình phạt hiệu suất.

+0

Bạn nói đúng. std :: endl xóa bộ đệm đầu ra, và "\ n" thì không. –

+0

Tôi biết lý do tại sao các hình phạt hiệu suất tồn tại. :-) Câu hỏi của tôi là: Tại sao ':: std :: endl' vẫn chỉ là" những gì đã làm "mặc dù nó có hình phạt hiệu suất đó? – Omnifarious

+1

Có lẽ vì hầu hết các lập trình viên thích nó khi người dùng của họ có thể thấy đầu ra thay vì buộc họ phải đợi cho đến khi bộ đệm lấp đầy. Với tốc độ của các thiết bị đầu ra thực tế, nó không bao giờ thực sự quan trọng. –

2

Tôi có xu hướng sử dụng endl với chuỗi video vì nó giúp dễ dàng phát hiện các dấu ngắt dòng bị thiếu.

2

Tôi đoán là văn bản hướng dẫn sử dụng std::endl với niềm tin rằng nó đơn giản và ít gây nhầm lẫn cho người mới bắt đầu, và sau đó mọi người quen với việc sử dụng nó.

Các vấn đề liên quan