rspec/rules/S3229/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

99 lines
2.4 KiB
Plaintext

== Why is this an issue?
Class members are initialized in the order in which they are declared in the class,
not the order in which they appear in the class initializer list.
To avoid errors caused by order-dependent initialization,
the order of members in the initialization list should match the order in which members are declared in a class.
The initialization order, as described https://en.cppreference.com/w/cpp/language/constructor#Initialization_order[here], is:
. If the constructor is for the most-derived class, virtual bases are initialized in the order in which they appear in depth-first left-to-right traversal of the base class declarations (left-to-right refers to the appearance in base-specifier lists)
. Then, direct bases are initialized in left-to-right order as they appear in this class's base-specifier list
. Then, non-static data members are initialized in order of declaration in the class definition.
=== Noncompliant code example
[source,cpp]
----
#include <iostream>
struct A {
A(int num) {
std::cout << "A(num = " << num << ")" << std::endl;
}
};
struct B {
int b;
};
class C : public A, B {
public:
int x;
int y;
C(int i) : B{i}, A{b}, y(i), x(y + 1) { } // Noncompliant
};
int main() {
C c(1); // Undefined behavior, might print "A(num = 0)"
std::cout << c.x << " " << c.y << std::endl; // might print "1 1"
}
----
=== Compliant solution
[source,cpp]
----
#include <iostream>
struct A {
A(int num) {
std::cout << "A(num = " << num << ")" << std::endl;
}
};
struct B {
int b;
};
class C : public A, B {
public:
int x;
int y;
C(int i) : A{i}, B{i}, x(i + 1), y(i) { }
};
int main() {
C c(1); // prints "A(num = 1)"
std::cout << c.x << " " << c.y << std::endl; // prints "2 1"
}
----
== Resources
* https://wiki.sei.cmu.edu/confluence/x/dXw-BQ[CERT, OOP53-CPP.] - Write constructor member initializers in the canonical order
* {cpp} Core Guidelines - https://github.com/isocpp/CppCoreGuidelines/blob/e49158a/CppCoreGuidelines.md#c47-define-and-initialize-member-variables-in-the-order-of-member-declaration[C.47: Define and initialize member variables in the order of member declaration]
ifdef::env-github,rspecator-view[]
'''
== Implementation Specification
(visible only on this page)
=== Message
Reorder these initializers to match their declaration order.
'''
== Comments And Links
(visible only on this page)
=== is duplicated by: S1266
endif::env-github,rspecator-view[]