It's been a long time since I've seen C++ -- 30 years of more, and obviously, things have changed a lot. I'm also spoiled with Scala, Julia etc, which take care of this magic under the covers, but... no more.... I'm tryihng to figure out why this doesn't work:
class Foo {
uint_fast8_t val1;
std::string name;
uint_fast16_t val2;
};
std::map<std::string, Foo> myMap;
myMap["Test"] = { 1, "Test2", 2 };
This fails to compile because several operators need to be overloaded for map to work. Note, this happens evne with a constructor defined such as
Foo(uint_fast8_t v1, std::string s, uint_Fast16_t v2) { };
If I just do a
myMap["Test"] = Foo()
This works because the constructor has the expected number of arguments (0) as opposed to 3. It's probably basic, and I'm sure I'm showing how long it's been, but what did I miss?
All the members of a class are by default private in contrast to struct where all the members are by default public so default value initialization of the member variables in a class via list initializer is not allowed.
Kindly refer this link for better understanding.
Hope this helps you
You have a class with default constructor,which takes zero arguments.
And you are trying to create he inline object with passing the three arguments.
I will suggest to add the parameterized constructor.
class Point {
private:
int x, y;
public:
// Parameterized Constructor
Point(int x1, int y1)
{
x = x1;
y = y1;
}
...
};
// Constructor called
Point p1(10, 15);
Basic C++ constructor types can be checked at link
Related
I'm trying to design a class - let's call it A for the sake of discussion - that will fulfill a specific set of requirements:
A must be a literal type to allow the compiler to initialize its global instances at compile time via constexpr constructors (many global const objects of this type are created in the source code). The reason for this is that A employs simple compile-time encryption (mostly XOR) on the integers. Decryption is later done at runtime while accessing the appropriate int.
Its central private field is a simple integer. However, the class has two constructors:
A::A(int x) and A::A(int x, int y, int z). If the first version is invoked, then later, at runtime, that single x will be used by the class internally whenever a method call that needs to use it is made. In contrast, if the second version with three parameters is used, it will be decided at runtime which one of x, y and z to use if a function that needs one is invoked.
A must be a single type; one type for the first constructor and another type for the second constructor is not satisfactory (A is frequently passed to functions as an argument, so without this constraint, I would need to duplicate or templatize all those functions).
A great majority of all A objects will be global constants, assignment will seldom happens, and if it does, it will certainly not be between an object with three ints and an object with one int or vice-versa.
To summarize: A will be instantiated as global const objects. If I initialize an object with a single int, that single int should be stored inside it (and nothing more). If I initialize it with three ints, then those three ints should be stored inside. There's no need to worry about assignment from a three-int object to a one-int object or vice versa, because they're all constants.
The solutions I have considered so far are as follows:
Make A a template; the template parameter would be what I called the StorageType. That storage would abstract access to that central int resource by exposing an accessor for it. The problem of choosing which int field to use would then be moved from the A to this helper storage type. The idea is roughly illustrated by this code:
template<typename StorageType>
class A
{
private:
StorageType storage;
public:
constexpr A(int x, int y, int z) :
storage(x, y, z)
{ }
constexpr A(int x) :
storage(x)
{ }
void doSomething()
{
auto theRightInt = storage.getInt();
// ...
}
};
Problem: violates constraint 3.
As before, but rather than templatize A on the StorageType, have a generic interface that describes the StorageType and store a unique_ptr to one inside A.
Problem: violates constraint 1.
Store the integers as a union:
union
{
struct
{
int x;
int y;
int z;
} intPack;
int singleInt;
};
In this variant, each A object - including those that only use a single int - has room for three possible ints. Another option would be to use boost::variant instead of the obsolete union.
Problem: This is wasteful - see point 4. If boost::variant is used, it violates constraint 1 since boost::variant, unlike std::variant from C++17, is not a literal type.
Rather than attempt to represent the "variance" of the central integer field inside A, do it externally: have the class always store a single int, and create a helper class - let's call it VariantA - that contains three versions of A, each initialized with what was x, y and z in the constructor mentioned in point 2. VariantA would have an accessor function that decides at runtime which A object to return.
Problem: Tedious to use because the accessor has to be invoked every single time:
VariantA a1(0, 1, 2);
VariantA a2(10, 20, 30);
auto a3 = a1.get() + a2.get();
someFunctionThatTakesAnA(a1.get());
// etc
Question:
Is there an elegant solution to this problem that I have missed, or will I have to choose one of the solutions I have considered (and rejected) above?
My platform is VC++, so use of C++11/4 is okay except some more esoteric parts, but the features from C++17 drafts are not yet available.
Seems like the best thing you could use is a conditionally sized range of ints:
class A {
std::array<int, 3> data;
bool one;
public:
constexpr A(int x): data{{x, 0, 0}}, one(true) { }
constexpr A(int x, int y, int z): data{{x, y, z}}, one(false) { }
constexpr size_t size() const { return one ? 1 : 3; }
constexpr const int* begin() const { return data.data(); }
constexpr const int* end() const { return data.data() + size(); }
};
I'm not entirely sure what your logic is for selecting which element, but if you have a 1-sized range, you get that element, if you have a 3-sized range, then you do whatever it is you need to do.
Regardless of the specific details, the main point is that you want a type that has 3 ints and a bool. You need to store 3 ints, you want it to be literal, and you want it to know whether it's storing 3 or 1 int. That pretty much spells out the type. The only thing left is to determine how you want the data access to look, and that's not specified.
A class/struct with 2 members?
A pointer to int and a bool (where the boolean say if the pointer point to one or three values)?
#include <iostream>
struct foo
{
bool single;
int const * p;
constexpr foo ( int const & x ) : single{true}, p{&x}
{}
constexpr foo ( int const * y ) : single{false}, p{y}
{}
};
constexpr int x{2};
constexpr int y[]{3, 5, 7};
int main ()
{
constexpr foo f1{x};
constexpr foo f3{y};
}
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.
I have been looking for quite some time for my question, but I haven't found any satisfying answer yet.
The question is fairly easy: What should I put between the brackets when I use Implicit Assignment for an Object.
I was always used to seeing something like this: The assign an int, you give it an int-value
class Point2D
{
private:
int m_nX;
int m_nY;
public:
// A specific constructor
Point2D(int nX, int nY)
: m_nX(nX), m_nY(nY) // So the int m_nX gets the int-value nX
{
}
}
But recently I found a tutorial where PARAMETERS were given to an object. (http://www.learncpp.com/cpp-tutorial/102-composition/)
class PersonalComputer
{
private:
CPU m_cCPU;
Motherboard m_cMotherboard;
RAM m_cRAM;
public:
PersonalComputer::PersonalComputer(int nCPUSpeed, char *strMotherboardModel, int nRAMSize)
: m_cCPU(nCPUSpeed), m_cMotherboard(strMotherboardModel), m_cRAM(nRAMSize)
// So the m_cCPU-object is given a parameter nCPUSpeed, and not another m_cCPU-object
{
}
};
So my question is: How does Implicit Assignment work for objects? And how can I assign an Object with an Object itself (e.g. give an m_cCPU2-object to the m_cCPU-object).
Thanks
This is called initialization (not "implicit assignment").
For a primitive type it means that object is given that initial value
int nX(5);
For a class type it means to call the class's constructor with those arguments:
Motherboard m("ABCDE");
To assign an initialize an object with another object in the initializer list you want to define a copy constructor
class CPU
{
CPU(const CPU& other)
: someSpeedVariable(other.someSpeedVariable) // Eg.
{}
}
Then you can do this in other classes.
class PC
{
PC(const CPU& cpu)
:m_cpu(cpu)
{}
CPU m_cpu;
}
I think this is what you're asking?
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.
I've been programming in C++ a while and I've used both methods:
class Stuff {
public:
Stuff( int nr ) : n( nr ) { }
private:
int n;
}
Or
class Stuff {
public:
Stuff( int nr ) {
n = nr;
}
private:
int n;
}
Note: This is not the same as this, similar but not the same.
What is considered best practice?
Initializer lists are preferred. See FAQ 10.6
One big advantage to using initializers: If an exception is thrown anywhere within the initializer list, the destructors will be called for those members that had already been initialized -- and only for those members.
When you use the contructor body to initialize the object, it's up to you to handle exceptions properly and unwind the object as appropriate. This is usually much harder to get right.
Use the initializer list when possible. For an int, it doesn't matter much either way, but for a more complex member object, you'd end up with the default constructor of the object being called, followed by an assignment to that object, which is likely to end up being slower.
Plus, you have to do it that way anyway for const members or members which don't have a default constructor.
If possible, use the first version.
The first is initializing using intializer lists, and actually calls the constructors of the members.
The second is assignment. If n was of a type with a default constructor, it the would have already been called, and then you'd be assigning to it. If n didn't have a default constructor, you'd be forced to use the first type. Likewise if n was a reference: int &n.
If there are no constructors of you members that directly take one of the parameters to your constructor, it may be worthwhile to add private static functions that can do the conversion for you.
I generally try to do the initializer list when I can. For one thing, this makes it explicit that you are initializing code in the constructor. const memebers have to be initialized this way.
If you just put code in the constructor's body, it is quite possible someone may decide to come along and move a big chunk of it into a non-constructor "setup" routine later.
It can be taken overboard though. I have a coworker who likes to create classes that have 2 pages of initilizer code, no constructor code, and perhaps 2 pages for the entire rest of the class' code. I find that really tough to read.
I want to add that you don't need to declare the initializer list on the Header (.h). It can be done at the implementation of the constructor (which is very common).
So then:
//Stuff.h
class Stuff {
public:
Stuff( int nr );
private:
int n;
}
//Stuff.cpp
Stuff::Stuff(int nr)
: n(nr)
{
//initalize complex members
}
is legal and imo concentrates the initialization of fields where it matters. Sometimes we need to initialize complex members in the body, so you have your initializer list and the complex initialization all in the .cpp file.
The second option is not initialization but assignment. With types that have user defined default constructors, the second option will call the default constructor and later on call the assignment operator (whether user defined or not) to assign the value.
Some types cannot be default initialized: If you have an attribute without default constructor, hold references (constant or not) or have constant attributes they must be initialized in the initializer list.
Arrays can be value-initialized in the initialization list, but not in the constructor body:
class X {
public:
X() : array() {} // value-initializes the array
// equivalent to:
// X() { for ( int i = 0; i < 10; ++i ) array[i]=0; }
private:
int array[10];
};
For POD types, you can value-initialize them in the initialization list but not inside the brackets:
class X {
public:
X() : pod() {} // value-initializes
// equivalent to (but easier to read and subtly faster as it avoids the copy):
// X() { pod = {}; }
private:
PODType pod;
};
Finally, some classes offer functionality through the use of constructors that will be more complex (if achievable) after default construction.
class X
{
public:
X() : v(10) {} // construct a vector of 10 default initialized integers
// equivalent to:
// X() { for ( int i = 0; i < 10; ++i ) v.push_back(0); }
private:
std::vector<int> v;
};
Last, whenever they are in fact equivalent, initialization lists are more idiomatic in C++.