Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

uninitialized local variable with c++11 default

Why does printing b.k give a warning when printing a.k does not? I Use VS2013

//warning C4700: uninitialized local variable 'b' used
#include<iostream> 

using namespace std;

struct A {
  A() {};
  int k;
};
struct B {
  B() = default;
  int k;
};

int main() {
  A a;
  cout << a.k << endl;
  B b;
  cout << b.k << endl; // this gives a warning, uninitialized local variable

  return 0;
}
like image 395
Merni Avatar asked Aug 26 '14 08:08

Merni


People also ask

What is the default value of an uninitialized variable in C?

(However, default initialization to 0 is a right practice for pointers and arrays of pointers, since it makes them invalid before they are actually initialized to their correct value.) In C, variables with static storage duration that are not initialized explicitly are initialized to zero (or null, for pointers).

How do I fix uninitialized local variables?

To fix this issue, you can initialize local variables when they're declared, or assign a value to them before they're used. A function can be used to initialize a variable that's passed as a reference parameter, or when its address is passed as a pointer parameter.

What default value is given to an uninitialized local and global variable in C?

My learning material from school says that global uninitialised variables are assigned 0 whereas uninitialised local variables are left unassigned and have a value that was present in that memory address. Observations: Variable 'first' seems to be assigned a random number every time as expected.

What will happen if you try to access an uninitialized local variable?

There will be no default values or ability to run the code. It will be a compile time error and your code won't run. If the variables were class fields they would get default values for certain types or null otherwise.


2 Answers

Accessing uninitialized variables is undefined behavior and no diagnostic is required. This means that you can get a warning for b.k (MSVC++), for a.k (g++) or for neither (Clang).

Standard quotes:

12.6.2 Initializing bases and members [class.base.init]

8 In a non-delegating constructor, if a given non-static data member or base class is not designated by a mem-initializer-id (including the case where there is no mem-initializer-list because the constructor has no ctor-initializer) and the entity is not a virtual base class of an abstract class (10.4), then

[bunch of non-applicable clauses]

— otherwise, the entity is default-initialized (8.5).

8.5 Initializers [dcl.init]

7 To default-initialize an object of type T means:

[bunch of non-applicable clauses]

— otherwise, no initialization is performed.

The 12.6.2/8 quote has this example:

struct C {
    C() { }    // initializes members as follows:
    A a;         // OK: calls A::A()
    const B b;   // error: B has no default constructor
    int i;       // OK: i has indeterminate value // <---------- your code
    int j = 5;   // OK: j has the value 5
};
like image 120
TemplateRex Avatar answered Oct 31 '22 16:10

TemplateRex


As per § 8.5 Initializers

if T has a non-trivial default constructor, the object is default-initialized;

Which means both a.k and b.k are not value initialized, access them are UB

To initialize A::k, you could put it in member initialize list

A():k(42) {};

For B::K, you could call it with:

B b = {}; // value initialize  members, k initialized to 0
like image 43
billz Avatar answered Oct 31 '22 16:10

billz