Неинициализированная локальная переменная с С++ 11 default

Почему печать b.k дает предупреждение при печати a.k? Я использую 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;
}

Ответ 1

Доступ к неинициализированным переменным - это undefined поведение, и диагностика не требуется. Это означает, что вы можете получить предупреждение для b.k (MSVС++), для a.k (g++) или для ни (Clang).

Стандартные кавычки:

12.6.2 Инициализация баз и членов [class.base.init]

8 В конструкторе без делегирования, если данный нестатический член данных или базовый класс не обозначается идентификатором mem-initializer-id (включая если нет mem-initializer-list, потому что конструктор не имеет ctor-инициализатора), и сущность не является виртуальным базовым классом абстрактный класс (10.4), то

[связка неприменимых предложений]

- в противном случае объект инициализируется по умолчанию (8.5).

8.5 Инициализаторы [dcl.init]

7 Для инициализации объекта типа T по умолчанию:

[связка неприменимых предложений]

- в противном случае инициализация не выполняется.

В приведенной ниже цитате 12.6.2/8:

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
};

Ответ 2

В соответствии с § 8.5 Инициализаторы

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

Это означает, что a.k and b.k не инициализируются значением, доступ к ним UB

Чтобы инициализировать A::k, вы можете поместить его в список инициализации члена

A():k(42) {};

Для B::K вы можете вызвать его с помощью:

B b = {}; // value initialize  members, k initialized to 0