0

The following code, as far as I can tell, correctly initializes the variables of the derived class B:

#include <utility>

struct A {
  int i;
};

struct B : A {
  int j;
  explicit B(A&& a) : A(std::move(a)), j{i} { }
};

int main()
{
  A a{3};
  B b(std::move(a));

  return 0;
}

Running cppcheck with --enable=all gives the warning:

[test.cpp:9]: (warning) Member variable 'A::i' is not initialized in the constructor. Maybe it should be initialized directly in the class A?

Is there a reason for this (false, I think) warning?

6
  • 2
    Why do you think A::i is properly initialized as your warning suggests? Commented Apr 27, 2022 at 14:51
  • @CaptainGiraffe I assume A has the default move/copy constructors, which in fact is used in the main(). Commented Apr 27, 2022 at 14:55
  • A::i will sit in an undefined state. Commented Apr 27, 2022 at 14:56
  • @CaptainGiraffe Did you make a typo in your first comment? You wrote: "Why do you think A::i is properly initialized" instead of "Why do you think A::i is not properly initialized" Commented Apr 27, 2022 at 14:57
  • 1
    A would get a default constructor with that error. But that constructor is never called. Not sure, why it shows the error for line 9. Commented Apr 27, 2022 at 15:40

1 Answer 1

3

Yes, this looks like a false positive. Base class subobjects are initialized before direct member subobjects and A(std::move(a)) will use the implicit move constructor which initializes this->i with a.i, so this->i will be initialized before the initialization of this->j is performed (which reads this->i).

The argument given to the constructor in main is also completely initialized via aggregate initialization, so a.i's value will not be indeterminate either.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks! It appears that cppcheck warns that I may improperly initialize A, although I believe it is sensible to assume, in the constructor of B, that the parameter is correctly initialized... Interestingly, if you add A()=delete; to A, the warning disappears.
@francesco As far as I know cppcheck doesn't actually fully parse C++ syntax and interpret its semantics, like e.g. Clang's or GCC's static analyzer would. Instead it often uses looser pattern rules. It might not actually be performing the overload resolution (correctly) and may instead (incorrectly) reason that lack of an user-declared constructor in A means that i cannot be initialized.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.