I have a class:
class C {
public:
C(): _a(a++){}
private:
static int a;
int _a;
};
int C::a = 0;
C c = C(); // c._a is 0
C d = C(); // d._a is 1
C e = C(); // e._a is 2
This works out as I'd expect: a and obj._a increment by 1. But if I assign c, d, and e to an unordered_map, they increment by 2:
unordered_map<int, C> map;
C c = C(); // c._a is 0
map[0] = c;
C d = C(); // d._a is 2
map[1] = d;
C e = C(); // e._a is 4
map[2] = e;
How can I assign c, d, and e to map and still make the static int a increment by 1?
The problem comes from your map. When you access map[0], the map will look for the entry 0 and if it does not exists, will instantiate it and returns to you a reference to the new instance.
Try using map.emplace(0, c) instead to add an item in your map.
Your problem is that the expression map[0] is creating a default constructed 'C' (and incrementing the counter), and then that object is assigned to.
The solution is to directly insert the object in the map with:
map.insert({0,c});
Related
I have been thinking and searching this but I can't solve this question.
I would like an object that when copied into another object, both objects share certain member variable. So, when I change the value of the member variable of object1, it's also changes the variable in object2. Example:
class ABC {
public:
int a = 5;
//...
}
int main() {
ABC object1;
ABC object2 = object1;
object2.a = 7; // now, object1.a is equal to 7
object1.a = 10; // now, object2.a is equal to 10
}
I know about copy constructors, but I am not sure if it applies here or there is
a better method. I have been thinking about using pointers or references, but can't make the trick.
Note that I don't want all the objects to share the same variable.
What you need is a pointer. The pointer points to the object and then all objects that copy the first one just copy the pointer so that they all point to the same thing. To make life easy we can use a std::shared_ptr to manage the allocation and deallocation for us. Something like:
#include <memory>
class Foo
{
private:
std::shared_ptr<int> bar;
public:
Foo() : bar(std::make_shared<int>()) {}
int& getBar() { return *bar; }
};
int main()
{
Foo a;
a.getBar() = 7;
Foo b = a;
b.getBar() = 10;
// now getBar returns 10 for both a and b
Foo c;
// a and b are both 10 and c is 0 since it wasn't a copy and is it's own instance
b = c;
// now b and c are both 0 and a is still 10
}
class Foo{
public:
Foo(){
cout <<"C ";
}
~Foo(){
cout <<"D ";
}
};
void func(){
Foo* p = new Foo;
p = NULL;
}
int main(){
Foo a;
for (int i=0; i<1; i++){
Foo b;
if (true){
Foo c;
}
func();
}
return 0;
}
For this question, the output is C C C D C D D, and if I delete the func() in the main function, the output become C C C D D D, I understand the first 3 C where it come from, but I don't understand the remaining, please explain it, thanks.
The scope of the object a is the scope of the outer code block of the function main. It is the first object that is created and the last object that is deleted.
int main(){
Foo a;
// ...
return 0;
}
C C C D C D D
| |
a a
Then in the for loop that has only one iteration there is created the object b that is deleted after the first iteration of the loop
for (int i=0; i<1; i++){
Foo b;
// ...
}
C C C D C D D
| | | |
a b b a
Then in the block scope of the statement if
if (true){
Foo c;
}
there is created and deleted the object c
C C C D C D D
| | | | | |
a b c c b a
After that the function func is called
func();
Inside the function there is created an unnamed object using the operator new and pointed to by the pointer p.
void func(){
Foo* p = new Foo;
p = NULL;
}
C C C D C D D
| | | | | | |
a b c c p b a
This object is not deleted because the operator delete is not called for this object. So there is a memory leak.
That is all.
C - a is constructed
C - b is constructed
C - c is constructed
D - c is desctructed becouse you leave the scope
C - an object Foo is dynamically allocated and pointed to by p, but since it is dynamically allocated, and never deleted, it's never destructed.
D - b is destructed
D - a is destructed
There order would be for C C C D C D D:
C - Construct A
C - Construct B
C - Construct C
D - Destruct C
C - Construct p (in func)
D - Destruct B
D - Destruct A
// memleak for p (in func)
When the func(); call is included, the steps taken are:
Foo a; -> C
Foo b; -> C
Foo c; -> C
Left the scope of Foo c -> D
func(); call ->
new Foo; -> C
Finished func() call, left the scope of Foo b -> D
Left the scope of Foo a -> D
Note that the Foo object created in func() is never destructured, meaning you have a memory leak.
I know that the correct way of push back an object in a vector is to declare an object of the same class and pass it by value as argument of method push_back. i.e. something like
class MyClass{
int a;
int b;
int c;
};
int main(){
std::vector<MyClass> myvector;
MyClass myobject;
myobject.a = 1;
myobject.b = 2;
myobject.c = 3;
myvector.push_back(myobject);
return 0;
}
My question is: it's possible to push back an object passing only the values of the object and not another object? i.e. something like
class MyClass{
int a;
int b;
int c;
};
int main(){
std::vector<MyClass> myvector;
int a = 1;
int b = 2;
int c = 3;
myvector.push_back({a, b, c});
return 0;
}
If you declare a, b, c as public,
class MyClass{
public:
int a;
int b;
int c;
};
then you could use list initialization:
myvector.push_back({a, b, c});
But it could be better to make a constructor
MyClass::MyClass(int a, int b, int c):
a(a), b(b), c(c)
{}
and then use vector::emplace_back
myvector.emplace_back(a, b, c);
To make it work you need at least a C++11 compiler and you need to make a constructor:
class MyClass {
int a;
int b;
int c;
public:
MyClass(int a_, int b_, int c_) : a(a_), b(b_), c(c_) {}
};
You could also make a, b and c public, but I'm guessing you don't want to do that, as it changes the interface of the class.
In response to your question "why is emplace_back better or more efficient than push_back":
By design, emplace_back() should avoid creating a temporary object and should construct "in place" at the end of the vector. With push_back({a, b, c}) you create a temporary MyClass object, which is then copied to the end of the vector. Of course, compiler optimizations may actually lead to same code being generated in both cases, but, by default, emplace_back() should be more efficient. This is further discussed here: push_back vs emplace_back .
I saw an online C++ test regarding the constructor. I can figure out most of the answers but am puzzled by some in the following. Hope someone can help me out.
Here's the example.
#include <iostream>
class A {
public:
A(int n = 0) : m_n(n) {
std::cout << 'd';
}
A(const A& a) : m_n(a.m_n) {
std::cout << 'c';
}
private:
int m_n;
};
void f(const A &a1, const A &a2 = A())
{
}
int main() {
A a(2), b;
const A c(a), &d = c, e = b;
b = d;
A *p = new A(c), *q = &a;
static_cast<void>(q);
delete p;
f(3);
std::cout << std::endl;
return 0;
}
What I don't really get is why "&d = c" doesn't output anything. Also adding another overloading constructor like A(const A *a) : m_n(a->m_n) { std::cout << 'b'; } doesn't output anything either for *q = &a. So what can I do to make it work?
Many thanks for any advice. I am very curious about this.
There's no output for these because d and q are not of type A, i.e. they are not A objects. d is a reference to A and q is a pointer to A. Initialising a reference and initialising or assigning a pointer does not manipulate the referred-to/pointed-to A object at all, hence no output.
To address your question - there is nothing to "make work," it works just as it should.
That to be more clear I will rewrite this statement
const A c(a), &d = c, e = b;
as
const A c(a);
const A &d = c;
Here d is declared as a reference to an object of type A. It does not create a new object. It refers to an object that is already created. In this case d referes to c. In fact d is simply an alias for object c.
This code snippet
A *p = new A(c), *q = &a;
also can be rewritten for simplicity
A *q = &a;
In this statement pointer q is simply assigned by the address of a. Neither object is created. Simply q now points to already created early object a.
&d = c doesn't output anything because you're not calling the constructor.
If we expand that code fragment a bit...
A &d = c
What your code is saying there is "declare d to be a reference to an object of type A, which points to c". Because you're creating a reference, you're not calling the constructor, c and d are the same object.
The same applies to q, but instead of creating a reference, you're creating a pointer and assigning it the address of an existing instance of type A. The constructor isn't called because you're not creating a separate object, you're linking to an existing one.
I have to write definition of the code below. I undarstand some basics of OOP Cpp, I know what is *x or &x, but that's not enough... The main fact is that i cant understand line B* p = new D, m, *k; i cant understand what m and *k stand for.
class B {
public:
virtual void msg() { cout << "classB"; }
};
class D: public B {
public:
virtual void msg() { cout << "classD"; }
};
int main() {
B* p = new D, m, *k;
p->msg(); k = &m; k->msg();
. . .
}
Help, if you can explain how (and why so) this code will work.
thanks, for your time.
It declares multiple variables at once. This is basically the same as:
B *p = new D;
B m;
B *k;
So p is a pointer to an instance of D allocated with new. m is a local instance of class B and k is a pointer to B that is later assigned to point at m.
The msg function is called on both allocated objects via the pointers p and k.
Note that * applies to each variable declaration separately. So B* a, b; doesn't declare two pointers, but instead declares one pointer and one local object. This is the reason, that many people prefer to write the * directly in front of the variable name: B *a, b makes this a bit more obvious.
In C++ you can declare more then one variable in one statement. Therefore B* p = new D, m, *k; declares the variables p, m and k. The * for pointer declarations binds to the variable name, therefore it's basically identical to
B* p = new D;
B m;
B* k;
Nothing fancy, it's just plain old C.
B* p = new D, m, *k;
is just shortcut for:
B* p = new D;
B m;
B* k;
p is a pointer to an object of the class B (or D, because it is a child of the class B). p->msg(); is similar to (*p).msg();. m is an object of the class B, so we can get pointer to it by & operator and store it in k (which is a pointer to an object of the class B).
And
B* p = new D, m, *k;
is just
B* p = new D;
B m;
B* k;
Notice: you should put * if it is needed each time