morpheuz
morpheuz

Reputation: 101

What is the difference between a custom default constructor and defaulted default constructor in C++

I am working on a program that behaves differently when I set the default constructor to when I omit it. Specifically I am building an object to pass it to a third-party library function. When I omit the default constructor, the function works as expected, however when I define it the function blocks and does not return control, so I think the problem is due to the constructor.

Below I show a summary excerpt of the part of the code that has to do with the problem.

class Config {
public:
    typedef std::shared_ptr<Config> SPtr;

    int frame;
    int numSolidParticles = 0;
    bool shapesChanged = false;

    Buffer* buffer;
    FlexParams params;  // struct

    // if omitted then the 3rd party method works as expected
    Config() {
    }
};

...

Config::SPtr config = std::make_shared<Config>();

initialize(config);

...
SetFlexParams(config->params);
// calls to other 3rd party methods that depends on config
...

// call 3rd party library's method that causes the issue
mapBuffer(config->buffer);

Update: What I'm trying to do is moving some of the initializations (e.g. frame, buffer and other fields not shown) in method inititalize to constructor.

Upvotes: 2

Views: 554

Answers (3)

YePhIcK
YePhIcK

Reputation: 5856

Default default constructor does one thing your manual default constructor does not: it properly default-constructs the members. I'm pretty sure that if you do either of the following your code will magically start working:

Option 1: Explicitly state default values for all the members (not just the two you have done so for)

int frame = 0;
int numSolidParticles = 0;
bool shapesChanged = false;

Buffer* buffer = nullptr;
FlexParams params = {};  // struct

Option 2: Remember to initialize all non-trivially-constructible members in your constructor

Config()
  : frame{0}
  , numSolidParticles{0}
  , shapesChanged{false}
  , buffer{nullptr}
  , params{} // I think this is the code generated by your compiler for the default default constructor
{
}

I personally prefer the first approach as it is clearer and way less prone to errors in a long run

Upvotes: 0

morpheuz
morpheuz

Reputation: 101

Although this does not answer the main question I would like to explain that the problem was being caused by a field of the FlexParams struct that I was forgetting to initialize.

This struct groups a large number of parameters to 3rd party library that are initialized in the initialize function. The funny thing is that when I do not define the constructor the field is initialized to 0 (which luckily was the correct value) while when I define it the field takes a random value.

The only reasonable explanation, as some of you mentioned in the comments, is that the issue was caused by undefined behavior.

Upvotes: 0

L. F.
L. F.

Reputation: 20579

What is the difference between a custom default constructor and defaulted default constructor?

Given a class X, if: ([class.ctor]/5)

  • X is a union that has a variant member with a non-trivial default constructor and no variant member of X has a default member initializer,

  • X is a non-union class that has a variant member M with a non-trivial default constructor and no variant member of the anonymous union containing M has a default member initializer,

  • any non-static data member with no default member initializer is of reference type,

  • any non-variant non-static data member of const-qualified type (or array thereof) with no brace-or-equal-initializer does not have a user-provided default constructor,

  • X is a union and all of its variant members are of const-qualified type (or array thereof),

  • X is a non-union class and all members of any anonymous union member are of const-qualified type (or array thereof),

  • any potentially constructed subobject, except for a non-static data member with a brace-or-equal-initializer, has class type M (or array thereof) and either M has no default constructor or overload resolution as applied to find M's corresponding constructor results in an ambiguity or in a function that is deleted or inaccessible from the defaulted default constructor, or

  • any potentially constructed subobject has a type with a destructor that is deleted or inaccessible from the defaulted default constructor.

then the defaulted default constructor of X is defined as deleted, whereas a hand-written X() {} will be ill-formed.

Otherwise, there is no difference.

Upvotes: 1

Related Questions