Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constructors for structs that don't do anything

Edit: Just to be clear, the struct doesn't do anything, as in it has no functions. I think I gave the impression that I thought using an initialiser list and leaving the body of the constructor empty was the issue at hand.

Say I'm using a struct to hold two values, and I have a constructor just so I can create an arbitrary struct like this:

struct twoValues
{
    int x;
    int y;

    twoValues(int x_, int y_):y(y_),x(x_)
    {}
};

someFunction(twoValues(1,2));

That saves me from having to do this:

twoValues anInstance;
anInstance.x=1;
anInstance.y=2;
someFunction(anInstance);

Edit: You're all correct, I could also initialise with the following:

twoValues anInstance = {1,2};

I see nothing wrong with this but I had some feedback from a C++ test and one of the negative feedback marks was "constructors for structs that don't do anything". I had limited contact with the guy testing me and so never asked why.

Is it a bad thing and why? I would rather carry on doing it.

like image 261
cool mr croc Avatar asked Jul 18 '12 08:07

cool mr croc


People also ask

Should structs have constructors?

Technically, a struct is like a class , so technically a struct would naturally benefit from having constructors and methods, like a class does.

Which constructor is not supported by struct?

Constructors in Structure A struct cannot contain a parameterless constructor. It can only contain parameterized constructors or a static constructor.

Can you make a constructor for a struct?

Constructors must have the same name as the class itself, and they can be defined with an arbitrary number of parameters. So, a struct can have multiple constructors using function overloading, but it's also possible to have no constructors for very simple structs with only built-in type members.

Can a struct have a default constructor?

C# does not allow a struct to declare a default, no-parameters, constructor. The reason for this constraint is to do with the fact that, unlike in C++, a C# struct is associated with value-type semantic and a value-type is not required to have a constructor.


2 Answers

It depends on what the struct is being used for. As others have said, the constructor means that the class is no longer a POD, and that aggregate initialization cannot be used for it. In particular, you cannot have something at namespace scope like:

TwoValues const table[] =
{
    { 1, 2 },
    { 3, 4 },
    // ...
};

You can have:

TwoValues const table[] =
{
    TwoValues(  1, 2  ),
    TwoValues(  3, 4  ),
    // ...
};

but it is more verbose, and it implies dynamic initialization, which may result in order of initialization issues.

On the other hand, without the constructor, you cannot create temporary instances on the fly. Instead of:

extern void f( TwoValues const& );
//  ...

f( TwoValues( 1, 2 ) );

you have to write:

extern void f( TwoValues const& );
//  ...

TwoValues tmp = { 1, 2 };
f( tmp );

If the object is dynamically allocated, it's even worse, since you either have to allocate first, then initialize, or create a temporary as above, and then write new TwoValues( tmp ) and use the implicit copy constructor.

You have to choose. Depending on what the struct is used for, one or the other will be preferred; on one hand, I have a lot of structs which are used exclusively in static tables, and intentionally don't have a constructor (and contain only types which support static initialization), and use them a lot for configuring code. On the other hand, I also have a lot of structs which are internal to a class, along the lines of Node in a tree or a graph; these almost always have a constructor, to facilitate creating them on the fly. There's no "correct" answer without knowing the role of the struct in your application.

like image 183
James Kanze Avatar answered Oct 06 '22 03:10

James Kanze


Declaring an empty constructor has side-effects..

Even though your constructor has an empty body it is still considered to be a constructor, and therefore certain object properties will be lost - such as the object being POD.

Some cases require the use of Plain Old Data-types, which can make it undesirable to do what you've done without a specific reason.

Read more about initialization without a defult constructor in the next section.


c++03 && c++11

You can initialize your members with values without explicitly defining a "constructor that doesn't do anything", just use the brace-initialization syntax as in the below snippet.

struct Obj {
  int x, y;
};

Obj a = {1,3}; /* a.x = 1, a.y = 2 */

c++03

The downside of not having a constructor is that you cannot initialize the object using = { ... } in certain circumstances when writing C++03.

C++11 fixes this for you, see the next section for relevant examples.


c++11

In C++11 the initialization using braces ( = { ... }) has been given increased functionality.

As seen in the below snippet where the defined constructor of Obj is called even though we use the same form of initialization as earlier in this post.

struct DoubleBoth {
  DoubleBoth (int x, int y)
    : x(x*2), y(y*2) 
  {}  

  int x, y;
};

The snippets below were all illegal prior to C++11:

DoubleBoth a = {1,2}; /* a.x = 2, a.y = 4 */

struct Wrapper {
  Wrapper ()
    : value {3,4}
  {}

  DoubleBoth value;
};

void func (DoubleBoth v = {1,2}) {  // c++11 only
  ...
}

func ({4,5}); // c++11 only, c++03 requires `DoubleBoth obj (0,1); func (obj);`
like image 45
Filip Roséen - refp Avatar answered Oct 06 '22 04:10

Filip Roséen - refp