rspec/rules/S5946/cfamily/rule.adoc
Fred Tingaud 22b4470f2a
Modify CFamily rules: CPP-4080 Refresh and standardize CppCoreGuidelines references (#3514)
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>
2023-12-20 10:08:18 +01:00

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[]