1

When I run this code, the VS compiler return error and says that t1.mem is uninitialized local variable.

#include <string>
#include <iostream>
struct T1
{
  int mem;
};

struct T2
{
  int mem;
  T2() { } // "mem" is not in the initializer list
};


int main()
{

  T1 t1;            // class, calls implicit default ctor
  std::cout << t1.mem << std::endl;
  const T2 t2;      // const class, calls the user-provided default ctor
                  // t2.mem is default-initialized (to indeterminate value)
  std::cout << t2.mem << std::endl;

}

If I have not assigned the constructor for struct T1, the compiler would have to generate the default constructor? And struct T2's constructor is empty initialization list, why it has no error tips?

TobiMcNamobi
  • 4,687
  • 3
  • 33
  • 52
  • 2
    This is perfectly valid code (albeit the values of `T1::mem` and `T2::mem` are indeed indeterminate). What is the EXACT error message you are seeing? It is an actual ERROR that stops compilation, or is it just a WARNING and the code runs? – Remy Lebeau Feb 08 '18 at 03:12
  • @RemyLebeau Error C4700 uninitialized local variable 't1' used ,stop compilation –  Feb 08 '18 at 03:26
  • 5
    @linsir That is actually a [warning, not an error](https://msdn.microsoft.com/en-us/library/axhfhh6x.aspx). You may have "treat warnings as errors" or the equivalent turned on. – Steve Feb 08 '18 at 03:30
  • @Steve I use vs compiler, it really can not run , and I can post photo –  Feb 08 '18 at 03:33
  • @linsir I don't doubt that. The link I posted is for the (well, "a") VC compiler. There is an option that causes warnings (that usually don't stop compilation) to be treated as errors, as an added precaution to avoid mistakes. – Steve Feb 08 '18 at 03:35
  • See [this answer](https://stackoverflow.com/a/2520873/425871). – Steve Feb 08 '18 at 03:36
  • @Steve It also has a runtime error. –  Feb 08 '18 at 03:45
  • @Steve but it can run , thanks –  Feb 08 '18 at 03:53
  • @linsir VS also has an option where it will detect when you use an uninitialized variable, but that's non-standard (specific to VS), you can turn it off somewhere else in the options. – user253751 Feb 08 '18 at 04:12
  • 3
    Possible duplicate of [Implicit constructor versus "empty" constructor](https://stackoverflow.com/questions/27237022/implicit-constructor-versus-empty-constructor) – xskxzr Feb 08 '18 at 08:32
  • VS 2017: It is an error. Not a warning. And I definitely have not turned on "Treat Warnings As Errors". – TobiMcNamobi Feb 08 '18 at 12:08
  • @RemyLebeau it is undefined behaviour. The compiler is **allowed** to stop when it finds UB on all code paths – Caleth Feb 08 '18 at 13:18

2 Answers2

0

My understanding is that the compiler is trying to protect you from its own generated code, and assumes "you know best" when using your provided constructor. In addition, checking whether or not your constructor actually ends up initializing T2.mem anywhere, including in the body of the constructor, could be an arbitrarily complex task, so the compiler authors may have decided that was a task better left unattempted than poorly executed.

This seems to be supported by the warning you would get from MSVC if you declared t1 as a const T1:

'const' automatic data initialized with compiler generated default constructor produces unreliable results

Note the wording "compiler generated default constructor".

Btw, you'll see this same warning if you request the compiler-generated default constructor with T2() = default.

Brian Heim
  • 81
  • 1
  • 9
0

Well, compilers aren't perfect. Sometimes they warn for one thing, but they don't for another, similar thing. Many compilers also offer runtime instrumentation of the generated code, where they insert special instructions that detect errors like use of uninitialized variables and will abort the program when that happens. But again, the system is not perfect and it can miss things.

In any event, you don't actually need a constructor. You can inline-initialize the class members:

struct T1
{
    int mem = 0;
};

The inline initialization will be used by default, unless a constructor initializes the member to something else:

struct T1
{
    int mem = 0;

    T1() = default;

    T1(int m) : mem(m) { }
};
// ...
T1 first; // first.mem == 0
T1 second(1); // second.mem == 1
Nikos C.
  • 50,738
  • 9
  • 71
  • 96