
Update all links to C++ Core Guidelines to `e49158a`.
Refresh done using the following script and some manual edits:
db76e34e74/personal/fred-tingaud/rspec/refresh-cppcoreguidelines.py
When re-using this script, be mindful that:
- it does not cover `shared_content`
- it does not properly escape inline code in links (e.g., "[=]" or "`mutex`es")
- it does not change `C++` to `{cpp}` in link titles.
Co-authored-by: Marco Borgeaud <marco.borgeaud@sonarsource.com>
87 lines
2.9 KiB
Plaintext
87 lines
2.9 KiB
Plaintext
== Why is this an issue?
|
|
|
|
When injecting ``++std::endl++`` into an output stream, two things happen:
|
|
|
|
* An end of line character ``++'\n'++`` is added to the stream
|
|
* The stream is flushed
|
|
|
|
In many situations, you don't need the stream to be flushed: It takes some time, and additionally, the stream is also flushed automatically in several circumstances:
|
|
|
|
* When the stream is closed
|
|
* In the case of ``++std::cout++``, each time an input is read on ``++std::cin++`` or an output is written on ``++std::cerr++``
|
|
* In the case of ``++std::cerr++``, each output is immediately written, the is no need to flush
|
|
|
|
Therefore, if your only goal is to add an end of line, ``++'\n'++`` is usually more efficient than ``++std::endl++``. If you do want to flush, you can be explicit and inject ``++std::flush++`` into the stream, or call the ``++flush++`` member function on the stream.
|
|
|
|
|
|
=== Noncompliant code example
|
|
|
|
[source,cpp]
|
|
----
|
|
void f() {
|
|
cout << "Hello world!" << endl << endl << "How are you?" << endl; // Noncompliant, 3 useless flushes
|
|
string s;
|
|
cin >> s;
|
|
cout << "Starting long operation now..." << endl; // Noncompliant, flushing is useful, but not explicit enough
|
|
longOperation();
|
|
cout << "Long operation is done" << endl; // Noncompliant
|
|
}
|
|
----
|
|
|
|
|
|
=== Compliant solution
|
|
|
|
[source,cpp]
|
|
----
|
|
void f() {
|
|
cout << R"(Hello world!
|
|
|
|
How are you?
|
|
)" << endl;
|
|
// Or
|
|
cout << "Hello world!\n\nHow are you?\n";
|
|
string s;
|
|
cin >> s;
|
|
cout << "Starting long operation now...\n" << flush;
|
|
longOperation();
|
|
cout << "Long operation is done\n";
|
|
}
|
|
----
|
|
|
|
|
|
== Resources
|
|
|
|
* {cpp} Core Guidelines - https://github.com/isocpp/CppCoreGuidelines/blob/e49158a/CppCoreGuidelines.md#slio50-avoid-endl[SL.io.50: Avoid `endl`]
|
|
|
|
|
|
ifdef::env-github,rspecator-view[]
|
|
'''
|
|
== Comments And Links
|
|
(visible only on this page)
|
|
|
|
=== on 19 Aug 2020, 00:32:48 Loïc Joly wrote:
|
|
We expect this rule to be quite verbose, for a limited value. But we believe it is still worth having it for its educational value.
|
|
|
|
We thought about having a rule trying to only detect uses of endl where we are confident that flushing is not needed (``++std::cout << "Hello" << endl << endl;++``) or several consecutive lines using endl without any function call in-between:
|
|
|
|
----
|
|
std::cout << "Hello" << endl;
|
|
std::cout << "Hello" << endl;
|
|
std::cout << "Hello" << endl;
|
|
----
|
|
But we believe it would be another rule (maybe part of SonarWay?), but still not much more valuable. So for now, we decided to stick to the simple rule.
|
|
|
|
|
|
Another option would be to flag only the cases where ``++\n++`` is more succinct than ``++endl++``:
|
|
|
|
|
|
----
|
|
std::cout << "Hello" << endl; // Noncompliant because...
|
|
std::cout << "Hello\n"; // ...alternative is shorter
|
|
std::cout << "Value:" << i << endl; // Compliant because...
|
|
std::cout << "Value:" << i << '\n'; // ...alternative is just as complex
|
|
----
|
|
But it is still favoring performances rather than correctness, which is usually not a great pattern...
|
|
|
|
endif::env-github,rspecator-view[]
|