If I have a simple struct Foo, defined like this, it's a POD:
#include <iostream>
#include <type_traits>
struct Foo {
int a;
int b;
bool c;
};
int main() {
std::cout << (std::is_pod<Foo>::value ? "POD" : "NON POD") << '\n'; // Prints "POD"
}
Now imagine I want to default initalize the members and directly do:
struct Foo {
int a;
int b;
bool c = true;
};
The struct is no longer a POD! Even with a constructor like this:
struct Foo {
int a;
int b;
bool c;
Foo() : a(0), b(0), c(false) {}
};
Foo has lost its PODness...
Now the tricky part begins. Imagine I want to add a constructor taking an a:
struct Foo {
int a;
int b;
bool c;
Foo(int a) : a(a), b(0), c(false) {}
};
Now Foo is definitely not a POD. BUT if a add a default constructor:
struct Foo {
int a;
int b;
bool c;
Foo() = default;
Foo(int a) : a(a), b(0), c(false) {}
};
Foo is now a POD!
So as you can see, even if I simply want to use a default value like in the second example, I lose the PODness, but I can regain it as long as I define an explicit default constructor.
So the question is: should we always add a default constructor so we can benefit from the PODness of the class and improve performance? It's too bad to lose performance just because I wanted to default initialize some members...
In other words, defining default value like in the second example makes the struct non POD and non trivial, which is bad performance-wise, so how can I default initialize values and keep the struct trivial? A simple solution would be to define an initFoo function that returns a default initialized Foo, like for example:
Foo initFoo() {
Foo foo;
foo.a = 0;
foo.b = 1;
foo.c = true;
return foo;
}
But this is not very C++, but is it the right thing to do anyway?
should we always add a default constructor so we can benefit from the PODness of the class
If you want a class to be POD, then it must be trivially default constructible, among the other requirements.
One way to achieve that requirement is to not declare any constructors nor default member initialisers. Another way is to define the default constructor as default. Latter is the only way if you want the class to have any non-default constructors.
It doesn't matter which approach you pick as far as PODness is concerned.
but is it the right thing to do anyway?
Your initFoo is a right way to return a Foo with specific values. Personally, I don't see value in the local variable, and would do this instead:
return {
0,
1,
true,
};
Unfortunately, we lose member names from the initialisers, at least until C++20 where we can write:
return {
.a = 0,
.b = 1,
.c = true,
};
Related
I have a POD struct like so
struct foo {
std::mutex m_foo_mutex;
int a;
int b;
int c;
//......
};
It has more fields than this but the structure should be apparent. The default copy ctor is, of course, ill formed because std::mutex's copy ctor is delete.
It's perfectly fine for my uses to copy this object, and give the copied object a new mutex. So I have defined something like this inside foo.
foo(const foo &foo2) : m_foo_mutex() {
a = foo2.a;
b = foo2.b;
c = foo2.c;
//.......
}
That's all well but it's quite ugly when this struct has 20+ fields, normally the compiler would hide this from me. Is there a cleaner way to express this, or am I stuck with this big ugly constructor?
You could wrap just your mutex in a copyable class:
struct CopyableMutex {
std::mutex mutex;
CopyableMutex() = default;
CopyableMutex(const CopyableMutex&) {};
CopyableMutex& operator= (const CopyableMutex&) {
return *this;
};
};
struct foo {
CopyableMutex m_foo_mutex;
int a;
int b;
int c;
};
You might want to come up with a better name than CopyableMutex though, as obviously it isn't actually copying the mutex!
Suppose I have a class Foo, with a member variable that is a std::vector of floats, bar. I then create an instance of Foo, called foo. Let's say that I do not know the length of bar before the program runs, but at the point when foo's constructor is called, I know that it's length should be x.
There are three ways I can think of to initialize the length of bar, and I'm just wondering which of the three most people tend to use. I have ranked them in order of what I would consider to be "best practice", but I'm more curious about what method people "actually" use in practice. Sometimes I use methods which make the code clearer to follow, rather than necessarily following best practice...
bar is a private member, and I resize it during foo's constructor, e.g. Foo foo(x){bar.resize(x)};
bar is a private member, and I call foo.ResizeBar(x) which resizes bar internally, after creating foo.
bar is a public member, and I call foo.bar.resize(x), after creating foo.
Or, in code:
1.
class Foo
{
private:
std::vector<float> bar;
public:
Foo(int x)
{
bar.resize(x);
};
};
int main()
{
Foo foo(100);
return 0;
}
2.
class Foo
{
private:
std::vector<float> bar;
public:
Foo()
{
};
void ResizeBar(int x)
{
bar.resize(x);
};
};
int main()
{
Foo foo;
foo.ResizeBar(100);
return 0;
}
3.
class Foo
{
public:
std::vector<float> bar;
Foo()
{
};
};
int main()
{
Foo foo;
foo.bar.resize(100);
return 0;
}
The problem with all three of your methods is that you're needlessly invoking the default initializer for your vector, and then modifying the already initialized vector to suit your needs.
You should be invoking the correct initializer using the initializer list:
Foo::Foo(std::size_t x) : bar(x, 0) { }
The best method is not in the list of options you posted. The best method is to initialize bar using member initializer lists.
Foo::Foo(int x) : bar(x) {}
Based on this question (asked a while ago)
inline-object-instantiation-and-transformation-in-java
Is there a way to instantiate and object and initialize it's members in a single line of c++, without the use of a constructor?
In java, as per the link:
JFrame aFrame = new JFrame();
aFrame.add(new JPanel() {{
setSize(100,100);
setLocation(50,50);
setBackground(Color.red);
}});
Can this be done in any way in c++?
EDIT: For example
class Foo{
public:
int test;
int test2;
};
int main(){
Foo foo(){{test=5 test2=4}}; //Like this
}
If the class is an aggregate (with no base classes, non-public members, virtual functions or user-declared constuctors), then you can use aggregate initialisation to initialise its members:
struct thing {
int a,b,c;
};
thing t = {1,2,3};
Otherwise, it can only be initialised by a constructor.
There's one idiom that allows syntax similar to Java. As with everything, it has its downsides as well. I'll leave it up to you to figure out whether it's right for this.
class Foo {
int a;
int b;
int c;
public:
Foo &setA(int val) {a = val; return *this;}
Foo &setB(int val) {b = val; return *this;}
Foo &setC(int val) {c = val; return *this;}
};
Now you can do the following:
auto foo = Foo().setB(2).setA(1).setC(3);
You can apply it to as many or few members as desired. However, it can be tricky in some cases to ensure you always have a valid object. Required initialization can go in the constructor.
Something along these lines that might be more natural is Boost.Parameter, which offers named parameter support that you can use to combine meaningful names with constructor arguments.
That is not an anonymous class. An anonymous class is one without a name.
If you want an anonymous (temporary) instance, and you can initialize it like so:
struct Foo {
int a;
int b;
};
void bar(Foo const &);
int main() {
bar(Foo{1,2});
}
See Mike's answer for the equivalent for a named instance of the named structure. The aggregate constraint is the same.
I wonder why people say:
"Inheriting class doesn't inherit the constructor".
If you could CAN use the parent class' constructor, and the parameterless constructor are called automatically no matter what.
Example:
#include <iostream>
using namespace std;
class A {
private :
int x;
public :
A () {
cout << "I anyway use parameter-less constructors, they are called always" << endl;
}
A (const int& x) {
this->x = x;
cout << "I can use the parent constructor" << endl;
}
};
class B : public A {
private :
int y;
public :
B() {
}
B (const int& x, const int& y) : A (x) {
this->y = y;
}
};
int main() {
B* b = new B(1,2);
B* b1 = new B();
return 0;
}
http://ideone.com/e.js/6jzkiP
So is it correct to 'say', constructors are inherited in c++ ? What is exact definition of "inherit" in programming languages ?
Thanks in advance.
I wonder why people say: "Inheriting class doesn't inherit the constructor".
Perhaps it is best to illustrate this with an example:
struct Foo
{
Foo(int, int) {}
};
struct Bar : Foo
{
};
What it means is that there is no Bar::Bar(int, int) constructor that you can call, despite the existence of a constructor with the same parameter list in the base class. So you cannot do this:
Bar b(42, 42);
In C++11, you can actually inherit constructors, but you must be explicit about it:
struct Bar : Foo
{
using Foo::Foo;
};
Now, you can say Bar b(42, 42);
What they mean is that constructor signatures are not inherited.
In your example, B does not have a constructor taking a single const int& even though its base class does. In this sense it has not "inherited" the constructor (but can still make use of it).
I think what they mean is:
struct A {
A(int, int) { }
};
struct B : public A {
};
int main()
{
A a(1, 2); // ok
B b(1, 2); // error
}
To compare with “non-special” member functions:
struct A {
void f() { }
};
struct B : public A {
};
int main()
{
A a;
B b;
a.f(); // ok
b.f(); // ok too
}
But of course, from within B you can call accessible A constructors (as automatically generated ones do). Ditto for the destructor.
Note that in C++11 you can use the “inheriting constructors” feature:
struct A {
A(int, int) { }
};
struct B : public A {
using A::A;
};
int main()
{
A a(1, 2); // ok
B b(1, 2); // ok now
}
A derived class can/must see base class constructors in order to invoke them, for consistency. However, their signature is not exposed in the derived class, hence, one cannot construct the class without an explicitly defined constructor, which forwards the required arguments to the base class constructor.
In C++11, one can inherit constructors: What is constructor inheritance?
Another approach to circumvent 'proxy constructors' in C++ < 11: How to define different types for the same class in C++
In your example, the default ("parameterless" as you say) constructor of B does invoke the default constructor of A, but this does not mean that B "inherited" that constructor, only that it "has access to" it. That is, A's default constructor is accessible from within B, yet it is not accessible from outside (no one can use A's default constructor from outside to construct an instance of B).
Another way to look at it is to ask, what is something frustrating about constructors and inheritance in C++? A common answer from some people (including myself) would be that there is no automatic facility which allows "pass-through" construction of base classes taking arguments from derived class constructors without explicitly declaring and defining the latter.
I have these structs.
struct V
{
int data[2];
V(int a,int b)
{
data[0] = a;
data[1] = b;
}
}
typedef std::vector<int> X;
struct A
{
B<V> member1;
B<X> member2;
A(V member1_, X member2_) : member1(member1_),member2(member2_){}
}
template<typename T>
struct B
{
T data;
B(T data_){data = data_;}
}
How do I create an object of struct A? I wish to declare an object A like so
A a;
and then use it later to assign member1 to it. This is because I would not know B's data until later in the program run. But the compiler would not let me and complains about default constructor in B, saying I don't have one. How do I write default constructors for B and A then while B is a template? Is there a better way to achieve this?
Thanks for your help.
Give struct B an empty default constructor. It will run the default constructor of data, too. You just need to make sure that T has a default constructor, too (actually, the current code of yours requires that, too - members are constructed before opening brace of constructor).