When I examine following program with it's output, I found quite confusing that to get a FrameA object by return value:
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?
FrameA()
will value-initialize the object (§5.2.3/2):
The expression
T()
, whereT
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, ifT
’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 forT
is called (and the initialization is ill-formed ifT
has no accessible default constructor);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With