emplace and try_emplace with copy constructor - c++

I have an issue with emplace and try_emplace as they always use the copy constructors when moving an object in.
#include <iostream>
#include <unordered_map>
#include <map>
using namespace std;
class Too {
public:
Too(int x, int y):x_(x), y_(y) {
cout << "init " << x_ << endl;
}
Too(const Too& too):x_(too.x_+1), y_(too.y_+1) {
cout << "Copy happen: x = " << x_ << endl;
}
~Too() {
cout << "delete too " << x_ << endl;
}
private:
int x_, y_;
};
std::map<int, Too> v;
int main()
{
v.emplace(100, Too{ 100,23 });
v.try_emplace(12, 12, 13);
Too t = Too(10, 11);
v.try_emplace(11, std::move(t));
}
output
init 100
Copy happen: x = 101
delete too 100
init 12
init 10
Copy happen: x = 11
delete too 10
delete too 101
delete too 12
delete too 11
As you can see, only v.try_emplace(12, 12, 13) do not use the copy constructor.
both v.emplace(100, Too{ 100,23 }) and v.try_emplace(11, std::move(t)) invoke the copy constructor.
So how can it be even when I use std::move(t)?
Any suggestion would be highly appreciated.
Thanks,

Since you've provided a copy constructor for your class, the move constructor Too::Too(Too&&) will not be implicitly generated by the compiler.
Moreover, when there is no move constructor available for a class, the copy constructor can be used.
For using the move constructor you have to explicitly provide an appropriate user-defined move constructor Too::Too(Too&&), then you will get the desired result.
You can add the move constructor either by adding Too(Too&&) = default; or writing your own move constructor which will do the initialization in the constructor initializer list.

Related

Constructer Calling order

I know when a constructer is being called, then it gets created in the memory, and when it gets out of the block it gets destroyed unless it's static.
Know I have this code:
#include <iostream>
#include <string>
using namespace std;
class CreateSample
{
private:
int id;
public:
CreateSample(int i)
{
id = i;
cout << "Object " << id << " is created" << endl;
}
~CreateSample()
{
cout << "Object " << id << " is destroyed" << endl;
}
};
void fuct()
{
CreateSample o1(1);
static CreateSample o2(2);
}
CreateSample o3(3);
void fuct2(CreateSample o);
int main()
{
fuct();
static CreateSample o4(4);
CreateSample o5(5);
fuct2(o5);
return 0;
}
void fuct2(CreateSample o)
{
CreateSample o6 = o;
}
and my concern is in object o5, why it's getting called once and gets destroyed 3 times?
When you wrote fuct2(o5); you're calling the function fuct2 and passing the argument by value. This means a copy of the argument will be passed to the function using the implicitly defined copy constructor. Thus you get the 2nd destructor call corresponding this object o.
Moreover, in fuct2 you have CreateSample o6 = o; which will also use the implicitly defined copy constructor to create o6. Thus you will get a third call to the destructor corresponding to this o6.
You can confirm this for yourself by adding a copy ctor as shown below:
class CreateSample
{
//other code here
public:
CreateSample(const CreateSample&obj): id(obj.id)
{
std::cout<<"Copy ctor called"<<std::endl;
}
};
And the output you will get is:
Object 5 is created <------ctor called for o5
Copy ctor called <------copy ctor called for parameter o
Copy ctor called <------copy ctor called for object o6
Object 5 is destroyed <------destructor called for o6
Object 5 is destroyed <------destructor called for o
Object 5 is destroyed <------destructor called for o5
Demo
Though in this particular example you don't strictly require a custom copy constructor or a custom copy assignment operator, they may be needed in other situations. Refer to the rule of three.
CreateSample o5(5); calls the constructor CreateSample(int). fuct2(o5); and CreateSample o6 = o; call the implicitly-defined default copy constructor CreateSample(CreateSample const&). All three of these variables (o6, o, and o5) call the destructor ~CreateSample() when their scope is exited.
The fix is to follow the rule of three and also define a copy constructor and copy-assignment operator:
class CreateSample
{
// ...
CreateSample(CreateSample const& o) {
id = o.id;
cout << "Object " << id << " is copy-constructed" << endl;
}
CreateSample& operator=(CreateSample const& o) {
cout << "Object " << id << " is copy-assigned from " << o.id << endl;
id = o.id;
return *this;
}
}
Demo on Compiler Explorer

C++ When member copy constructors are called

Given the code
#include <iostream>
#include <vector>
class Entity {
public:
Entity(const int x, const int y) :
x(x), y(y)
{
this->entities.push_back(*this);
}
int x, y;
std::vector<Entity> entities;
};
int main() {
auto p = Entity(10, 20);
std::cout << p.entities.size() << '\n';
std::cout << p.x << ' ' << p.y << "\n\n";
std::cout << p.entities[0].entities.size() << '\n';
std::cout << p.entities[0].x << ' ' << p.entities[0].y << '\n';
return 0;
}
When entities.push_back is called, the Entity should be copied to the vector. When copied all members should have their copy constuctors called in the following order: (x, y, entities). The problem is in the entities constructor, the "std::vector" constructor should call the "Entity" constructor that will call the "std::vector" constructor again, resulting in a infinite loop.
But according to the output:
1
10 20
0
10 20
The "std::vector" copy constructor is not called.
Where is my error? I'm forgetting some implementation detail?
the "std::vector" constructor should call the "Entity" constructor that will call the "std::vector" constructor again, resulting in a infinite loop
Nope.
The std::vector<Entity> copy constructor will call the Entity copy constructor.
The Entity copy constructor copies the member vector as it currently exists (empty). It does not run the code in the two-element Entity constructor that push_back something to the vector.
You're copying yourself in a constructor, which is generally a bad practice since the object is not yet fully constructed. In this case, the vector is still empty when you call push_back.

Class Constructor is not getting called when creating a vector with class objects

I am creating a vector with class objects as below.
#include <iostream>
#include <vector>
using namespace std;
class myclass
{
public:
myclass(int a = 0) : x(a)
{
cout << "myclass constructor" << endl;
}
int x;
};
int main()
{
vector<myclass> v(2, 1);
cout << "size : " << v.size() << endl;
cout << v[0].x << endl;
cout << v[1].x << endl;
}
As per my understanding 2 objects will be created with value '1'. But constructor is getting called only once. When I print the values of the objects, both objects are printing x values as '1'. Below is the output.
myclass constructor
size : 2
1
1
I couldn't understand why constructor is not getting called twice.
1) Is copy constructor getting called here?
I tried to write copy constructor in the class as below
myclass(myclass &obj)
{
x = obj.x;
cout << "Copy Constructor" << endl;
}
but it is throwing following errors while compiling.
vector.cpp:15:9: note: no known conversion for argument 1 from ‘const myclass’ to ‘myclass&’
vector.cpp:10:9: note: myclass::myclass(int)
myclass(int a = 0) : x(a)
^
vector.cpp:10:9: note: no known conversion for argument 1 from ‘const myclass’ to ‘int’
2) Is there any rule that we should not define copy constructor if we are going to create vector of objects of that class? What are the rules we should follow if we are creating vector with user defined class objects?
The copy constructor requires a const reference. Use myclass(const myclass &obj) for the copy constructor.
As per my understanding 2 objects will be created with value '1'. But
constructor is getting called only once.
The constructor is called once and then the object is copied a number of times.
Then the picture is clear from the output:
myclass constructor
Copy Constructor
Copy Constructor
size : 2
1
1
Remember that the vector will also resize and have to copy the elements sometimes.
try
myclass(const myclass &obj)
{
x = obj.x;
cout << "Copy Constructor" << endl;
}
As for part 2, general rule apply : create copy constructor where default member-by member copying will fail.

How to pass functional-object (functor) by reference or pointer?

The following C++ code is a simplification of a problem I am trying to solve.
It generates a random number then calls the functional-object to make a decision and generate output.
The code details a functional-object, a function and the main program. Sample output is provided. I've added copy constructor, copy assignment, move constructor & move assignment code to try and elucidate what is happening here.
I'm relatively new to using functional objects and have been trying to work out why there are so many calls to the copy constructor, move constructor and destructor. In fact excess calls to the destructor are causing trouble in my real application where functional-objects have allocated resources in their constructors.
My question is:
Is there a way modify this code so that a pointer or reference to the functional-object is passed around; so that there is no need to copy or move or destruct objects except when the program is finished?
#include <functional>
#include <iostream>
#include <stdlib.h>
#include <chrono>
#include <thread>
class RelativeValue
{
public:
//Constructor
RelativeValue(const int bdry) : boundary(bdry)
{
std::cout << "RelativeValue: Constructor" << std::endl;
}
//Copy Constructor
RelativeValue(const RelativeValue &orig) : boundary(orig.boundary)
{
std::cout << "RelativeValue: Copy Constructor" << std::endl;
}
//Copy assignment
RelativeValue& operator= (const RelativeValue &that)
{
std::cout << "RelativeValue: Copy Assignment Constructor" << std::endl;
if (this != &that)
{
boundary = that.boundary;
}
return *this;
}
//Move constructor
RelativeValue(RelativeValue &&orig) /*noexcept NOT VS2013*/ : boundary(orig.boundary)
{
std::cout << "RelativeValue: Move Constructor" << std::endl;
}
//Move Assignment
RelativeValue& operator=(RelativeValue &&that) /*noexcept NOT VS2013*/
{
std::cout << "RelativeValue: Move Assignment Constructor" << std::endl;
if (this != &that)
{
boundary = that.boundary;
}
return *this;
}
//Operators
bool operator==(const RelativeValue &anotherRelativeValue) const
{
return (boundary == anotherRelativeValue.boundary);
}
void operator()(const int &in)
{
if (in < boundary)
{
std::cout << in << " < " << boundary << std::endl;
}
else if (in > boundary)
{
std::cout << in << " > " << boundary << std::endl;
}
else if (in == boundary)
{
std::cout << in << " == " << boundary << std::endl;
}
}
~RelativeValue()
{
std::cout << "RelativeValue: Destructor Called." << std::endl;
}
private:
int boundary;
};
void reactor(const int &iterations, const std::function <void(int)> &functionObject)
{
int runLoop(0);
int number(0);
int returnValue(0);
srand(time(NULL));
while (runLoop < iterations)
{
number = rand() % 100 + 1;//in the range 1 to 100
functionObject(number);//call the functional-object
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
++runLoop;
}
}
int main(int argc, char* argv[])
{
//Want to create the functional-object here.
RelativeValue rv(50);
//Then pass the functional object to the reactor.
std::thread t1(reactor, 10, rv);//do the work.
t1.join();//wait for it.....
return 0;
}
Output:
RelativeValue: Constructor
RelativeValue: Copy Constructor
RelativeValue: Move Constructor
RelativeValue: Move Constructor
RelativeValue: Move Constructor
RelativeValue: Copy Constructor
RelativeValue: Destructor Called.
85 > 50
RelativeValue: Destructor Called.
RelativeValue: Destructor Called.
63 > 50
47 < 50
92 > 50
80 > 50
12 < 50
57 > 50
10 < 50
66 > 50
89 > 50
RelativeValue: Destructor Called.
RelativeValue: Destructor Called.
RelativeValue: Destructor Called.
Functors are designed to act as powered-up plain old C functions, that means they should be small, or at least, be easy to copy. Functions are usually passed by value. Take the Standard Library <algorithm>s as an example.
But even if you use operator() for things that are not only a simple function, i.e. your functors carry a lot of state and machinery inside, you should not worry about copy ctors, destructors, etc. During release build with optimizations enabled most of that object bypassing around will be erased.
If you don't trust on compiler skills, the best solution is to use std::ref() and std::cref(), which create references with correct value semantics.

Why is copy-constructor not called in this case?

I encountered a code snippet and thought that it would call copy-constructor but in contrast , it simply called normal constructor . Below is the code
#include <iostream>
using namespace std;
class B
{
public:
B(const char* str = "\0")
{
cout << "Constructor called" << endl;
}
B(const B &b)
{
cout << "Copy constructor called" << endl;
}
};
int main()
{
B ob = "copy me";
return 0;
}
What you've discovered that B ob = "copy me"; notionally creates a B from the literal and then copy constructs ob, but that the compiler is allowed to elide the copy and construct directory into ob. g++ even elides the copy with no optimization enabled at all.
You can observe that this is the case by making your copy constructor private: The code will fail to compile even though the compiler won't actually use the copy constructor (the standard requires that copy constructors be accessible even when the call is elided).