Regarding the following, are there any reasons to do one over the other or are they roughly equivalent?
class Something
{
int m_a = 0;
};
vs
class Something
{
int m_a;
Something(int p_a);
};
Something::Something(int p_a):m_a(p_a){ ... };
The two code snippets you posted are not quite equal.
class Something
{
int m_a = 0;
};
Here you specify the value with which to initialise, i.e. 0, at compile time.
class Something
{
int m_a;
Something(int p_a);
};
Something::Something(int p_a):m_a(p_a){ ... };
And here you do it at run time (or possibly at run time), with the value p_a not known until the constructor is called.
The following piece of code comes closer to your first example:
class Something
{
int m_a;
Something();
};
Something::Something() : m_a(0) { /* ... */ };
What you have to consider here is that in the first case, the value appears directly in the class definition. This may create an unnecessary dependency. What happens if you need to change your 0 to 1 later on? Exposing the value directly in the class definition (and thus, usually, in a header file) may cause recompilation of a lot of code in situations where the other form of initialisation would avoid it, because the Something::Something() : m_a(0) part will be neatly encapsulated in a source file and not appear in a header file:
// Something.h - stable header file, never changed
class Something
{
int m_a;
Something();
};
// Something.cpp - can change easily
Something::Something() : m_a(0) { /* ... */ };
Of course, the benefits of in-class initialisation may vastly outweigh this drawback. It depends. You just have to keep it in mind.
The first form is more convenient if you have more than one constructor (and want them all to initialise the member in the same way), or if you don't otherwise need to write a constructor.
The second is required if the initialiser depends on constructor arguments, or is otherwise too complicated for in-class initialisation; and might be better if the constructor is complicated, to keep all the initialisation in one place. (And it's also needed if you have to support pre-C++11 compilers.)
The first form is new to C++11 and so at this point isn't terribly well supported, especially if you need to support a variety of older compilers.
Otherwise they should be roughly equivalent when a C++11 compiler is available.
Elaborating on Christian Hackl's answer.
The first form allows to initialize m_a and have a default c'tor at the same time. Or you can even be explicit in your code and define a constructor with the default keyword:
class Something
{
int m_a = 0;
// explicitly tell the compiler to generate a default c'tor
Something() = default;
};
With the second form, an auto-generated default c'tor would leave m_a uninitialized, so if you want to initialize to a hard-coded value, you have to write your own default c'tor:
class Something
{
int m_a;
// implement your own default c'tor
Something() : m_a(0) {}
};
class Something
{
int m_a = 0;
};
is equivalent to
class Something
{
int m_a(0);
};
So, doing
class Something
{
int m_a;// (0) is moved to the constructor
public:
Something(): m_a(0){}
};
yields a uniform syntax for initialization that requires or does not require run-time input.
Personally I don't like the first form because it looks like an "declaration then assignment", which is complete misconception.
If you change the code like what Christian did to make them do the same thing. Now it is a tradeoff between compile-time optimization (which Christian explained completely) and run-time optimization.
class Foo{
public:
Vector<double> vec1;
.
.
.
Vector<double> vecN;
}
Imagine you have to initialize each vector by some predefined doubles. If the program must instantiate many and many objects of this class, it is better to initialize the vectors in the header file to make the user happy by reducing the run-time!
Even though it's supported, this type of initialization will create bugs that will be pretty hard to track down. It's the type of "aesthetic optimization" that you will regret a couple months down the road.
See the example below:
class_x_1.h:
class X
{
private:
int x = 10;
public:
int GetX();
};
class_x_2.h:
class X
{
private:
int x = 20;
public:
int GetX();
};
class_x.cpp:
#include "class_x_1.h" // implementation uses the version that initializes x with 10
int X::GetX()
{
return x;
}
main.cpp:
#include "class_x_2.h" // main includes definition that initializes x with 20
#include <iostream>
int main()
{
X x;
std::cout << x.GetX() << std::endl;
return 0;
}
Output:
20
As expected, it will return 20 because this is the version that initializes x with 20. However, if you go to the implementation of X, you might expected it to be 10.
Related
I'm developing a class for my AVR cpu.
The class is going to handle all port related operations like Set, Read, etc;
Constructor looks like:
(...)
public:
Port(volatile uint8_t * DDR, volatile uint8_t * PORT);
(...)
And it is constructed at the beginning of the main():
int main()
{
Port PortA(&DDRA, &PORTA);
(...)
}
Now I want to make sure that nowhere else in the program object with same parameters would be constructed. It is sure that I cannot create array or map to find it out and throw an exception. It must be done at compile time. So basicly I want to force avr-g++ to check if any other Port(the same first parameter OR the same second parameter) exists in current project.
All functions uses pointers / references to Port objects.
How about the following?
The address of the pointers has to be known at compile-time.
template<int *p>
class Tester
{
public:
static Tester& GetInstance()
{
static Tester t;
return t;
}
private:
Tester() {}
};
int i;
int main()
{
Tester<&i>& t = Tester<&i>::GetInstance();
}
If you only want one instance of a class, then why use classes? The whole purpose of classes, is that you can have multiple intances. Just stick to global variables and free functions.
This is not pretty, but it does get the job done. 10 years experience says embedded work tends to be like this at times. :/
I tested this with a simple class under MSVC, you'll have to adapt for your needs, but it does demonstrate the principle.
Declare your class like this in the header:
class t
{
public:
#ifdef ALLOW_CTOR
t(int i);
~t();
#endif
int get();
private:
int m_i;
};
Then in exactly one file add the line:
#define ALLOW_CTOR 1
include the header file, declare your port instances as file scope variables, and then implement all the class methods of your class, ctor, dtor, accessors, etc.
If you do not place ALLOW_CTOR line in other source files, they can still use the accessor methods in your class, but they can't use the constructor. In the absence of the correct constructor, MSVC complains because it tries to use the default copy constructor, but since the parameter lists don't match, it fails. I suspect the compiler you're using will fail in some way, I'm just not sure exactly what the failure will be.
#Neil Kirk
If failure to provide a declaration of a ctor at all for a compilation unit leads to undefined behavior, then there are ways to solve that.
class t
{
#ifdef ALLOW_CTOR
public:
#else
private:
#endif
t(int i);
public:
~t();
int get();
private:
int m_i;
};
marks the ctor as public in one, but private in all other compilation units, leading to a well defined error: the inability to access a private member function.
This may be a silly question, but still I'm a bit curious...
Recently I was working on one of my former colleague projects, and I've noticed that he really loved to use something like this:
int foo(7);
instead of:
int foo = 7;
Is this a normal/good way to do in C++ language?
Is there some kind of benefits to it? (Or is this just some silly programming style that he was into..?)
This really reminds me a bit of a good way how class member variables can be assigned in the class constructor... something like this:
class MyClass
{
public:
MyClass(int foo) : mFoo(foo)
{ }
private:
int mFoo;
};
instead of this:
class MyClass
{
public:
MyClass(int foo)
{
mFoo = foo;
}
private:
int mFoo;
};
For basic types there's no difference. Use whichever is consistent with the existing code and looks more natural to you.
Otherwise,
A a(x);
performs direct initialization, and
A a = x;
performs copy initialization.
The second part is a member initializer list, there's a bunch of Q&As about it on StackOverflow.
Both are valid. For builtin types they do the same thing; for class types there is a subtle difference.
MyClass m(7); // uses MyClass(int)
MyClass n = 3; // uses MyClass(int) to create a temporary object,
// then uses MyClass(const MyClass&) to copy the
// temporary object into n
The obvious implication is that if MyClass has no copy constructor, or it has one but it isn't accessible, the attempted construction fails. If the construction would succeed, the compiler is allowed to skip the copy constructor and use MyClass(int) directly.
All the answers above are correct. Just add that to it that C++11 supports another way, a generic one as they say to initialize variables.
int a = {2} ;
or
int a {2} ;
Several other good answers point out the difference between constructing "in place" (ClassType v(<constructor args>)) and creating a temporary object and using the copy constructor to copy it (ClassType v = <constructor arg>). Two additional points need to be made, I think. First, the second form obviously has only a single argument, so if your constructor takes more than one argument, you should prefer the first form (yes, there are ways around that, but I think the direct construction is more concise and readable - but, as has been pointed out, that's a personal preferance).
Secondly, the form you use matters if your copy constructor does something significantly different than your standard constructor. This won't be the case most of the time, and some will argue that it's a bad idea to do so, but the language does allow for this to be the case (all surprises you end up dealing with because of it, though, are your own fault).
It's a C++ style of initializing variables - C++ added it for fundamental types so the same form could be used for fundamental and user-defined types. this can be very important for template code that's intended to be instantiated for either kind of type.
Whether you like to use it for normal initialization of fundamental types is a style preference.
Note that C++11 also adds the uniform initialization syntax which allows the same style of initialization to be used for all types - even aggregates like POD structs and arrays (though user defined types may need to have a new type of constructor that takes an initialization list to allow the uniform syntax to be used with them).
Yours is not a silly question at all as things are not as simple as they may seem. Suppose you have:
class A {
public:
A() {}
};
and
class B {
public:
class B(A const &) {}
};
Writing
B b = B(A());
Requires that B's copy constructor be accessible. Writing
B b = A();
Requires also that B's converting constructor B(A const &) be not declared explicit. On the other hand if you write
A a;
B b(a);
all is well, but if you write
B b(A());
This is interpreted by the compiler as the declaration of a function b that takes a nameless argument which is a parameterless function returning A, resulting in mysterious bugs. This is known as C++'s most vexing parse.
I prefer using the parenthetical style...though I always use a space to distinguish from function or method calls, on which I don't use a space:
int foo (7); // initialization
myVector.push_back(7); // method call
One of my reasons for preferring using this across the board for initialization is because it helps remind people that it is not an assignment. Hence overloads to the assignment operator will not apply:
#include <iostream>
class Bar {
private:
int value;
public:
Bar (int value) : value (value) {
std::cout << "code path A" << "\n";
}
Bar& operator=(int right) {
value = right;
std::cout << "code path B" << "\n";
return *this;
}
};
int main() {
Bar b = 7;
b = 7;
return 0;
}
The output is:
code path A
code path B
It feels like the presence of the equals sign obscures the difference. Even if it's "common knowledge" I like to make initialization look notably different than assignment, since we are able to do so.
It's just the syntax for initialization of something :-
SomeClass data(12, 134);
That looks reasonable, but
int data(123);
Looks strange but they are the same syntax.
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.
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.
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);`
It's much safer to have this kind of constructor, than to initialize with a list.
When you initialize with a list :
twoValues anInstance = {1, 2};
It really depends on the order of the members in the struct. Which in most cases is totaly random to begin with.
If another programmer happens to add another member, or to sort the members by alphabet, it wont work correctly.
Having a constructor that assigns the values to the right member by NAME is much safer.
You've stopped twoValues from being a POD and have prevented instances of the struct from being default- or value- initialized which are often desirable properties. Personally, I would prefer to have a free function for making temporary instances if you need a simple C++03 friendly approach.
E.g.
twoValues makeTwoValues(int x_, int y_)
{
twoValues tmp = { x_, y_ };
return tmp;
}
void f() {
someFunction(makeTwoValues(1,2));
}
E.g. initializing a member of type twoValues
class X {
twoValues tv;
public:
X(int x, int y) : tv(makeTwoValues(x, y)) {}
};
Probably because you can initialize it like this:
twoValues anInstance = {1, 2};
However, without the constructor you cannot initialize a anInstance in another struct's initializer list in C++03. For example:
struct Bar {
twoValues v_;
Bar() : v_(1,2) {} // error!
Bar() { v_ = {1,2}; } // have to assign value in constructor body
Bar() : v_{1,2} {} // OK in C++11
};
so in fact the constructor does something, and it does serve a very useful purpose in C++03. It is less of an issue in C++11.
There is nothing wrong with this contructor.
Also, it does something, it affect values to x and y, which is what I would expect from such a constructor.
But, maybe there are some coding rules in your company that says that you should do it another way. In that case I would recommend you ask the person that gave you the feedback and make the necessary modifications.
The constructor makes the struct a non-POD which may not be desirable in some cases.
If your struct doesn't have constructor, then your struct will be POD1, and you will be allowed to initialize like this:
twoValues anInstance = {1,2}; //C++03 and C++11 both!
twoValues anInstance {1,2}; //C++11 only
which are good.
1. Actually there are other things which make a struct non-POD. So just because your struct doesn't have constructor doesn't necessarily mean it is POD. You would like to see this post to know what those other things are.
Structures can have constructors, and the syntax is the same as for classes in C++. The difference between a class and a struct is that class-members are private by default, while struct-members default to public, however Unions will not allow constructors in the structs. You can make a constructor on the union though.
In C++, is it possible to call a function of an instance before the constructor of that instance completes?
e.g. if A's constructor instantiates B and B's constructor calls one of A's functions.
Yes, that's possible. However, you are responsible that the function invoked won't try to access any sub-objects which didn't have their constructor called. Usually this is quite error-prone, which is why it should be avoided.
This is very possible
class A;
class B {
public:
B(A* pValue);
};
class A {
public:
A() {
B value(this);
}
void SomeMethod() {}
};
B::B(A* pValue) {
pValue->SomeMethod();
}
It's possible and sometimes practically necessary (although it amplifies the ability to level a city block inadvertently). For example, in C++98, instead of defining an artificial base class for common initialization, in C++98 one often see that done by an init function called from each constructor. I'm not talking about two-phase construction, which is just Evil, but about factoring out common initialization.
C++0x provides constructor forwarding which will help to alleviate the problem.
For the in-practice it is Dangerous, one has to be extra careful about what's initialized and not. And for the purely formal there is some unnecessarily vague wording in the standard which can be construed as if the object doesn't really exist until a constructor has completed successfully. However, since that interpretation would make it UB to use e.g. an init function to factor out common initialization, which is a common practice, it can just be disregarded.
why would you wanna do that? No, It can not be done as you need to have an object as one of its parameter(s). C++ member function implementation and C function are different things.
c++ code
class foo
{
int data;
void DoSomething()
{
data++;
}
};
int main()
{
foo a; //an object
a.data = 0; //set the data member to 0
a.DoSomething(); //the object is doing something with itself and is using 'data'
}
Here is a simple way how to do it C.
typedef void (*pDoSomething) ();
typedef struct __foo
{
int data;
pDoSomething ds; //<--pointer to DoSomething function
}foo;
void DoSomething(foo* this)
{
this->data++; //<-- C++ compiler won't compile this as C++ compiler uses 'this' as one of its keywords.
}
int main()
{
foo a;
a.ds = DoSomething; // you have to set the function.
a.data = 0;
a.ds(&a); //this is the same as C++ a.DoSomething code above.
}
Finally, the answer to your question is the code below.
void DoSomething(foo* this);
int main()
{
DoSomething( ?? ); //WHAT!?? We need to pass something here.
}
See, you need an object to pass to it. The answer is no.
I recently came across classes that use a configuration object instead of the usual setter methods for configuration. A small example:
class A {
int a, b;
public:
A(const AConfiguration& conf) { a = conf.a; b = conf.b; }
};
struct AConfiguration { int a, b; };
The upsides:
You can extend your object and easily guarantee reasonable default values for new values without your users ever needing to know about it.
You can check a configuration for consistency (e.g. your class only allows some combinations of values)
You save a lot of code by ommiting the setters.
You get a default constructor for specifying a default constructor for your Configuration struct and use A(const AConfiguration& conf = AConfiguration()).
The downside(s):
You need to know the configuration at construction time and can't change it later on.
Are there more downsides to this that I'm missing? If there aren't: Why isn't this used more frequently?
Whether you pass the data individually or per struct is a question of style and needs to be decided on a case-by-case basis.
The important question is this: Is the object is ready and usable after construction and does the compiler enforce that you pass all necessary data to the constructor or do you have to remember to call a bunch of setters after construction who's number might increase at any time without the compiler giving you any hint that you need to adapt your code. So whether this is
A(const AConfiguration& conf) : a(conf.a), b(conf.b) {}
or
A(int a_, int b_) : a(a_), b(b_) {}
doesn't matter all that much. (There's a number of parameters where everyone would prefer the former, but which number this is - and whether such a class is well designed - is debatable.) However, whether I can use the object like this
A a1(Configuration(42,42));
A a2 = Configuration(4711,4711);
A a3(7,7);
or have to do this
A urgh;
urgh.setA(13);
urgh.setB(13);
before I can use the object, does make a huge difference. Especially so, when someone comes along and adds another data field to A.
Using this method makes binary compatibility easier.
When the library version changes and if the configuration struct contains it, then constructor can distinguish whether "old" or "new" configuration is passed and avoid "access violation"/"segfault" when accessing non-existant fields.
Moreover, the mangled name of constructor is retained, which would have changed if it changed its signature. This also lets us retain binary compatibility.
Example:
//version 1
struct AConfiguration { int version; int a; AConfiguration(): version(1) {} };
//version 2
struct AConfiguration { int version; int a, b; AConfiguration(): version(2) {} };
class A {
A(const AConfiguration& conf) {
switch (conf.version){
case 1: a = conf.a; b = 0; // No access violation for old callers!
break;
case 2: a = conf.a; b = conf.b; // New callers do have b member
break;
}
}
};
The main upside is that the A object can be unmutable. I don't know if having the AConfiguration stuct actualy gives any benefit over just an a and a b parameter to the constructor.
Using this method makes binary compatability harder.
If the struct is changed (one new optional field is added), all code using the class might need a recompile. If one new non-virtual setter function is added, no such recompilation is necessary.
I would support the decreased binary compatibility here.
The problem I see comes from the direct access to a struct fields.
struct AConfig1 { int a; int b; };
struct AConfig2 { int a; std::map<int,int> b; }
Since I modified the representation of b, I am screwed, whereas with:
class AConfig1 { public: int getA() const; int getB() const; /* */ };
class AConfig2 { public: int getA() const; int getB(int key = 0) const; /* */ };
The physical layout of the object might have change, but my getters have not and the offset to the functions have not either.
Of course, for binary compatibility, one should check out the PIMPL idiom.
namespace details { class AConfigurationImpl; }
class AConfiguration {
public:
int getA() const;
int getB() const;
private:
AConfigurationImpl* m_impl;
};
While you do end up writing more code, you have the guarantee here of backward compatibility of your object as long as you add supplementary methods AFTER the existing ones.
The representation of an instance in memory does not depend on the number of methods, it only depends on:
the presence or absence of virtual methods
the base classes
the attributes
Which is what is VISIBLE (not what is accessible).
And here we guarantee that we won't have any change in the attributes. The definition of AConfigurationImpl might change without any problem and the implementation of the methods might change too.
The more code means: constructor, copy constructor, assignment operator and destructor, which is a fair amount, and of course the getters and setters. Also note that these methods can no longer be inlined, since their implementation are defined in a source file.
Whether or not it suits you, you're on your own to decide.