Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does default constructor zero-initialize member array variable?

Tags:

c++

arrays

When I examine following program with it's output, I found quite confusing that to get a FrameA object by return value:

  1. when a empty ctor is defined, the member array field is remain uninitialized
  2. when let the compiler generate the ctor, the member array field is initialized to all 0

    auto a = f();       // f() --> return A();
    

Given following SSCCE

#include <cstring>
#include <iostream>
#include <chrono>
#include <algorithm>

using namespace std;

const int MAX = 9999999;

struct FrameA {
  // FrameA() {}
  // FrameA(const FrameA &v) { memcpy(data, v.data, sizeof(data)); }
  char data[1000];
};

FrameA f(int i) { return FrameA(); }

int test(int odd) {
  int sum = 0;
  auto begin = chrono::steady_clock::now();
  for (int i = 0; i < MAX; ++i) {
    auto v = f(odd);
    sum += v.data[0] + v.data[330];
  }
  auto end = chrono::steady_clock::now();
  cout << chrono::duration_cast<chrono::milliseconds>(end - begin).count()
       << " (milliseconds)" << endl;
  return sum;
}

int _tmain(int argc, _TCHAR *argv[]) {
  test(0);
  test(1);
  return 0;
}

When defined an empty ctor, the output is like:

g++ v4.8.1

72 (milliseconds)
73 (milliseconds)

But use compiler generated ctor, the output is:

g++ v4.8.1

1401 (milliseconds)
1403 (milliseconds)

I also tested on VC12, the result is similar.

After examine the assembly, I found when using compiler generated ctor:

  for (int i = 0; i < MAX; ++i) {
    auto v = f(odd);
00A31701  push        3E8h  
00A31706  lea         eax,[ebp-3F8h]  
00A3170C  push        0  
00A3170E  push        eax  
00A3170F  call        _memset (0A32460h)               ;; memset FrameA to 0
    sum += v.data[0] + v.data[330];
00A31714  movsx       eax,byte ptr [ebp-3F8h] 

But using an empty ctor won't call memset to set the array in FrameA to zero.

Is there any explanation to this?

BTW, I searched the C++ 11 draft n3242, but Chap 8.5 zero-initialize and default-initialize seems doesn't covered this case. Is there anything I missed?

like image 668
Xin Huang Avatar asked Mar 22 '23 06:03

Xin Huang


1 Answers

FrameA() will value-initialize the object (§5.2.3/2):

The expression T(), where T is a simple-type-specifier or typename-specifier for a non-array complete object type or the (possibly cv-qualified) void type, creates a prvalue of the specified type, which is value-initialized

Value-initializing a non-union class type that doesn't have a user-provided constructor will zero-initialize it (§8.5/7):

if T is a (possibly cv-qualified) non-union class type without a user-provided constructor, then the object is zero-initialized and, if T’s implicitly-declared default constructor is non-trivial, that constructor is called.

This zero-initializes each of its members.

Value-initializing a class type that does have a user-provided constructor will simply called the constructor (which in your case, does not initialise the array) (§8.5/7):

if T is a (possibly cv-qualified) class type (Clause 9) with a user-provided constructor (12.1), then the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);

like image 169
Joseph Mansfield Avatar answered Apr 06 '23 08:04

Joseph Mansfield