My question is give below to avoid multiple copies in vector copying.
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
class DataValue {
public:
DataValue() { std::cout << "DataValue constructor called" << std::endl; }
DataValue(DataValue const& other) { cout << "DataValue copy constructor called" << std::endl; }
~DataValue() { std::cout << "DataValue destructor is called" << std::endl; }
private:
};
class ItemDataHistory {
public:
ItemDataHistory() { std::cout << "ItemDataHistory constructor called" << std::endl; }
// ItemDataHistory(ItemDataHistory const & other) { std::cout << "ItemDataHistory copy constructor called" << std::endl; }
~ItemDataHistory() { std::cout << "ItemDataHistory destructor called" << std::endl; }
std::vector<DataValue>& GetVecDataValues() { return m_vecDataValues; }
private:
std::vector<DataValue> m_vecDataValues;
};
class DataReply {
public:
DataReply() { std::cout << "Data reply constructor is called "<< std::endl; }
~DataReply() { std::cout << "Data reply destructor is called "<< std::endl; }
DataReply(const DataReply& ) { std::cout << "Data reply copy constructor is called "<< std::endl; }
std::vector<ItemDataHistory>& GetItemDataHistories() { return m_vecItemData; }
private:
// The list of DataValue
std::vector<ItemDataHistory> m_vecItemData;
};
void main()
{
DataValue dv1, dv2, dv3;
ItemDataHistory itmDH;
itmDH.GetVecDataValues().reserve(3);
itmDH.GetVecDataValues().push_back(dv1);
itmDH.GetVecDataValues().push_back(dv2);
itmDH.GetVecDataValues().push_back(dv3);
DataReply dr;
dr.GetItemDataHistories().reserve(1);
dr.GetItemDataHistories().push_back(itmDH); // Here copy consturtor of itemdatahistory is called and all data values are copied.
// Here I want to avoid data values constructor to be called again how can I avoid this
// How can I directly insert values of dv1, dv2, dv3 into "dr" with out using "itmDH"?
return;
}
Note here I cannot use pointer in above std::vector m_vecItemData; in data reply class as these are interface classes from libary and don't have control on it and I am calling function so function may use data while data in scope
My question is given in above comment in code. Reason is that I have thousands of data values. To avoid multiple constructors of data values to be called, I want to insert data values directly to data reply (i.e., with out using itmDH local variable)
and other questions is
How I can reserve space of data values inside data reply?
With C++11, you have two options:
make your type ItemDataHistory movable and move your data (if possible) with dr.GetItemDataHistories().push_back(std::move(itmDH));
look into new member function of containers, e.g. emplace_back().
In C++11, you can use move semantics.
Instead of doing this:
itmDH.GetVecDataValues().push_back(dv1);
itmDH.GetVecDataValues().push_back(dv2);
itmDH.GetVecDataValues().push_back(dv3);
You could do this:
itmDH.GetVecDataValues().push_back(std::move(dv1));
itmDH.GetVecDataValues().push_back(std::move(dv2));
itmDH.GetVecDataValues().push_back(std::move(dv3));
Instead of copying values, they are simply moved into the vector.
And instead of copying itmDH
dr.GetItemDataHistories().push_back(itmDH);
you could move it as well:
dr.GetItemDataHistories().push_back(std::move(itmDH));
In addition you also need move constructors. Here's an example:
DataValue(DataValue&& other){
std::cout << "DataValue move constructor called" << std::endl;
}
You may also declare and define move assignment operator:
DataValue& operator=(DataValue&& other){
std::cout << "DataValue move assigment operator is called" << std::endl;
return *this;
}
In order to fully understand move semantics (and rvalue references as well) please take a look at the following links:
http://www.cprogramming.com/c++11/rvalue-references-and-move-semantics-in-c++11.html
http://thbecker.net/articles/rvalue_references/section_01.html
Related
Is there a way to avoid copying when initializing a vector?
The code below will produce the following output.
#include <iostream>
#include <vector>
using namespace std;
struct Ticker {
std::string m_ticker;
Ticker() {
std::cout << "Default constructor" << std::endl;
}
Ticker(const std::string& ticker)
: m_ticker(ticker)
{
std::cout << "Parametrized constructor" << std::endl;
}
Ticker(Ticker&& other)
{
std::cout << "Move constructor" << std::endl;
m_ticker = other.m_ticker;
other.m_ticker = "";
}
Ticker(const Ticker& x)
{
std::cout << "Copy constructor" << std::endl;
m_ticker = x.m_ticker;
}
~Ticker()
{
std::cout << "Destructor" << std::endl;
}
friend std::ostream& operator << (std::ostream& os, const Ticker& dr);
};
std::ostream& operator << (std::ostream& os, const Ticker& dr)
{
os << "|" << dr.m_ticker << "|";
return os;
}
int main() {
std::vector<Ticker> table = std::move(std::vector<Ticker>{std::move(Ticker("MSFT")), std::move(Ticker("TSL"))});
for (const auto& row: table)
{
std::cout << row << std::endl;
}
return 0;
}
This produces the following output:
Parametrized constructor
Move constructor
Parametrized constructor
Move constructor
Copy constructor
Copy constructor
Destructor
Destructor
Destructor
Destructor
|MSFT|
|TSL|
Destructor
Destructor
Is there a way to avoid the copy constructor and initialize in-place or just move without copying?
If you use
std::vector<Ticker> table = std::vector<Ticker>{Ticker("MSFT"), Ticker("TSL")};
You will get
Parametrized constructor
Parametrized constructor
Copy constructor
Copy constructor
Destructor
Destructor
|MSFT|
|TSL|
Destructor
Destructor
Which has 4 constructor calls instead of the 6 you currently have. 2 of those calls are for Ticker("MSFT") and Ticker("TSL") and then the additional two copies are because initializer lists store the elements in them as const, so they have to be copied into the vector as you can't move from a const object.
To get the bare minimum of 2 constructor calls you'll need to use the emplace_back member function like
std::vector<Ticker> table; // create empty vector
table.reserve(2); // allocate space for 2 Tickers but create nothing
table.emplace_back("MSFT"); // directly construct from "MSFT" in the reserved space
table.emplace_back("TSL"); // directly construct from "TSL" in the reserved space
which has the output of
Parametrized constructor
Parametrized constructor
|MSFT|
|TSL|
Destructor
Destructor
If you want a syntax like std::vector<Ticker> table = std::vector<Ticker>{Ticker("MSFT"), Ticker("TSL")};, but without the extra overhead, you could wrap the emplace_back solution in a factory function like
template <typename T, typename... Args>
auto make_vector(Args&&... args)
{
std::vector<T> data;
data.reserve(sizeof...(Args));
(data.emplace_back(std::forward<Args>(args)), ...);
return data;
}
and then you would use it like
auto table = make_vector<Ticker>("MSFT", "TSL");
I have overridden default copy constructor and assignment operator with only prints and not returning any thing.
How ever, the class works fine i.e., it gets copied and assigned properly.
As you can see the display() method also gets called properly. (I was expecting crash or segmentation fault as copy constructor and Assignment operator are overridden and doing nothing.
I have compiled the same with different compilers including the online one and still output remains the same.
My Question:
Why is the class working properly? Without showing any errors?
I was expecting it to crash or malfunction such as outputting garbage values.
'
class Pizza
{
public:
Pizza(std::string string) { std::cout << "Ctor :" << string << std::endl; }
~Pizza() { std::cout << "Dtor" << std::endl; }
Pizza(const Pizza& rhs){ std::cout << "Copy Constructor" << std::endl; }
Pizza& operator=(const Pizza& rhs){ std::cout << "Assignment Operator" << std::endl;}
void display(){std::cout << "Display method is called on Pizza" << std::endl; }
};
int main()
{
Pizza pizza = Pizza("1");
Pizza tizza = pizza;
tizza = pizza;
pizza.display();
tizza.display();
}'
The output for the code with g++ (Mingw Compiler) on windows 10 and other compilers too is:
Ctor :1
Copy Constructor
Assignment Operator
Display method is called on Pizza
Display method is called on Pizza
Dtor
Dtor
Looks like I found the reason:
Thanks to #Igor Tandetnik, he had mentioned the same thing in comment on the same day when the question was asked. However since, the comment was brief and I'm still in learning phase, I was unable to get the whole picture from the comment. Hence, decided to write the answer, with a bit of explanation. Which will be helpful for someone like me, Some day :) .
Reason:
- I haven't being using the any data members in the class.
- I'm only using the class method in the above code. Since, all the objects uses the same class methods (i.e., class methods are per class, not per object.)
- The main motive of the copy constructor is to copy the data members from one object of the class to another object.
- I haven't declared any non-static data member for the class, which are created per object. Declaring non-static members for the above would surely result in undefined behavior of the class. Such data members having garbage values.
- Hence, the above code works fine with non-correct copy constructor and move assignment operator.
Below is the code which will give the garbage values for the data members because of incorrect assignment operator and copy constructor.
//g++ 5.4.0
#include <iostream>
class Pizza
{
public:
Pizza(std::string string, int data) : m_string(string), m_data(data) { std::cout << "Ctor :" << string << std::endl; }
~Pizza() { std::cout << "Dtor" << std::endl; }
void set(std::string string, int data) { m_string = string; m_data = data; }
Pizza(const Pizza& rhs){ std::cout << "Copy Constructor" << std::endl; }
Pizza& operator=(const Pizza& rhs){ std::cout << "Assignment Operator" << std::endl;}
void display()
{
std::cout << "Display method is called on Pizza" << std::endl;
std::cout << "string: " << m_string << " Data: " << m_data << std::endl;
}
private:
std::string m_string;
int m_data;
};
int main()
{
Pizza pizza = Pizza("Test", 99);
Pizza tizza = pizza;
tizza = pizza;
pizza.display();
tizza.display();
}
Bottom Line: Copy constructor, move constructor, assignment operator will make sense the most only when the class has non-static data members.
#include <iostream>
#include <vector>
class A
{
public:
A() { std::cout << "constructor" << std::endl; }
~A() { std::cout << "destructor" << std::endl; }
};
int main()
{
std::vector<A> myvec;
myvec.push_back(A());
myvec.push_back(A());
myvec.clear();
return 0;
}
output:
constructor
destructor
constructor
destructor
destructor
destructor
destructor
There are five calls to the destructor here. The first two are due to the temporaries which are passed to push_back. There are three other calls, but I expected one two extra calls.
myvec.clear() will clear only two contents so destructor of A should call only two times (instead of three). why there is one extra time destructor is called?
But, if I push_back only one element to the vector, instead of two, the output is as I expected.
The call to std::vector::clear isn't really important in this context because, when myvec goes out of scope, its contents will be destroyed anyway.
Let's consider
class A
{
public:
A() { std::cout << "constructor" << std::endl; }
~A() { std::cout << "destructor" << std::endl; }
A (const A &) { std::cout << "A(A&)\n"; }
};
int main()
{
std::vector<A> myvec;
std::cout << "First\n";
myvec.push_back(A());
std::cout << "Second\n";
myvec.push_back(A());
std::cout << '\n'; // to separate the final destruction
myvec.clear();
}
which outputs
First
constructor <-- First A _temporary_ object created when pushing_back
A(A&) <-- vector makes a *copy* of the temporary
destructor <-- Temporary A is destroyed
Second
constructor <-- Second A _temporary_ object created when pushing_back
A(A&) <-- Reallocation happens: vector can't copy because it ran out of space
A(A&) <-- Copy of the second temporary
destructor <-- Destroy of the temporary
destructor <-- Destroy of the first element
destructor
destructor
If you std::vector::reserve some space, you can get rid of the copies made by the reallocation
std::vector<A> myvec;
myvec.reserve(8);
which confirms what said
First
constructor
A(A&)
destructor
Second
constructor
A(A&)
destructor
push_back is still making copies of the parameter: this can be further optimized by making your class moveable.
A(A&&) noexcept = default;
A& operator=(A&&) noexcept = default;
First
constructor
destructor
Second
constructor
destructor
This is most likely due to the reallocation that takes place between the first and the second push_back. If you reserve some space ahead of time, then the deallocations are going to be 2 after the two push_backs, as you have expected.
Try this slightly modified version of your program. There is now a copy constructor and an optional reserve (see comment in the program). It will be a lot clearer what is going on.
#include <iostream>
#include <vector>
using namespace std;
class A
{
public:
A() { cout << " constructor" << endl; }
A(const A & a) { cout << " copy constructor" << endl; }
~A() { cout << " destructor" << endl; }
};
int main()
{
vector<A> myvec;
// myvec.reserve(100); // <<< remove comment to see the difference
cout << "pushback 1" << endl;
myvec.push_back(A());
cout << "pushback 2" << endl;
myvec.push_back(A());
cout << "pushback 3" << endl;
myvec.push_back(A());
cout << "clear" << endl;
myvec.clear();
cout << "end clear" << endl;
return 0;
}
The following example, beats me. I've been so far thinking, that when functor is being used, the object gets constructed once and the same object is used multiple times, when used with for_each algorithm and that seems to be correct.
However, even though, only one object gets constructed, but multiple objects are destroyed. Now, this beats me.
class print
{
public:
void operator()(int i)
{
std::cout << i << std::endl;
}
print()
{
std::cout << "Constructor " << std::endl;
}
~print()
{
std::cout << "Destructor" << std::endl;
}
};
int main()
{
std::vector<int> v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
std::cout << "After assigning values " << std::endl;
for_each(v.begin() , v.end() , print());
std::cout << "After printing values " << std::endl;
}
The output is as follows
After assigning Values
Constructor
10
20
30
Destructor
Destructor
Destructor
After printing values.
How is this possible?
Don't forget about the copy constructor (the Rule of Three can help you to remember this):
class print
{
public:
void operator()(int i)
{
std::cout << i << std::endl;
}
print()
{
std::cout << "Constructor " << std::endl;
}
print(const print& other) {
std::cout << "Copy Constructor " << std::endl;
}
~print()
{
std::cout << "Destructor" << std::endl;
}
};
int main()
{
std::vector<int> v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
std::cout << "After assigning values " << std::endl;
for_each(v.begin() , v.end() , print());
std::cout << "After printing values " << std::endl;
}
Output:
After assigning values
Constructor
Copy Constructor
10
20
30
Copy Constructor
Destructor
Destructor
Destructor
After printing values
Here is how I have for_each on my system:
template<class _InIt,
class _Fn1> inline
_Fn1 _For_each(_InIt _First, _InIt _Last, _Fn1 _Func)
{ // perform function for each element
for (; _First != _Last; ++_First)
_Func(*_First);
return (_Func); // a copy could be created here (C3)
}
template<class _InIt,
class _Fn1> inline
_Fn1 for_each(_InIt _First, _InIt _Last, _Fn1 _Func)
{ // perform function for each element
_DEBUG_RANGE(_First, _Last);
_DEBUG_POINTER(_Func);
return (_For_each(_Unchecked(_First), _Unchecked(_Last), _Func)); // a copy created here (C2)
}
So, essentially, this is how it could look
for_each(v.begin() , v.end() , print()); // print functor created (constructor)
// a copy created here (C1)
Now, this is completely upto the implementation if copy elision is done or not. The Standard does allow that latitude to elide away the copy constructor e.g. C3 may be eliminated.
A good way to control gcc behavior here is the -fno-elide-constructors which ensures that code does not elide away the copy constructor
You are only printing "Constructor" from the default constructor. Instances of your type can come into existance from the copy-constructor as well. Copies might be being made through the call stack. Unless you specify otherwise you get a default copy constructor for free. You can add a copy constructor and also print out "Constructor" if you want to verify this.
No matter how it's constructed, you will still see the one-and-only destructor fire and print-out "Destructor".
I would say that the for_each created copies of the print() functor which calls the implicit copy constructor defined by the compiler which doesn't appear in your code (not the same as your defined constructor above).
I was going through Josuttis's "Using Map's as associative arrays" (from The C++ Standard Library - A Tutorial and Reference, 2nd Edition) and came across Using a std::map as an associative array on Stack Overflow. Now I have more questions on the constructors that are called when inserting into a map.
Here is my sample program (not using best coding practices; please excuse me for that):
class C
{
public:
string s;
C() { cout << "default " << endl;}
C(const string& p) : s(p)
{ cout << "one param" << endl;}
C(const C& obj)
{
if (this != &obj)
{
s = obj.s;
}
cout << "copy constr" << endl;
}
C& operator = (const C& obj)
{
if (this != &obj)
{
s = obj.s;
}
cout << "copy initializer" << endl;
return *this;
}
};
int main()
{
map<int,C> map1;
C obj("test");
cout << "Inserting using index" << endl;
map1[1] = obj;
cout << "Inserting using insert / pair" << endl;
map1.insert(make_pair(2,obj));
}
The output for this program is:
one param
Inserting using index
default
copy constr
copy constr
copy initializer
Inserting using insert / pair
copy constr
copy constr
copy constr
copy constr
I was assuming that initializing the map by index should call the default constructor and followed by the assignment operator.
But executing map1[1] = obj creates following output;
Inserting using index
default
copy constr
copy constr
copy initializer
Can someone help me to understand the initialization better?
If you read the specification for std::map, it says that operator[] is equivalent to (in this case)
(*((this->insert(make_pair(1,C()))).first)).second
So this explains all the constructor calls you see. First it calls the default constructor C(). Then it calls make_pair, which copies the C object. Then it calls insert, which makes a copy of the pair object you just made, calling the C copy constructor again. Finally it calls the assignment operator to set the inserted object to the one you are assigning it to.
Don;t know.
But this is interesting:
#include <string>
#include <map>
#include <iostream>
using namespace std;
class C
{
public:
string s;
C()
{
cout << "default " << endl;
}
C(const string& p)
: s(p)
{
cout << "one param(" << s << ")" << endl;
}
C(const C& obj)
:s(obj.s)
{
cout << "copy constr(" << s << ")" <<endl;
}
C& operator = (const C& obj)
{
cout << "copy initializer\t" <<;
C copy(obj);
std::swap(s,copy.s);
return *this;
}
};
int main()
{
map<int,C> map1;
cout << "Inserting using index" << endl;
map1[1] = C("Plop");
}
It looks like the default one is created and copied around.
Then the external one is just assinged over it once it has been put in place.
Inserting using index
default
copy constr()
copy constr()
one param(Plop)
copy initializer copy constr(Plop)
What happens if you simply execute map[1];? This may involve internal copies, depending on the implementation of map your standard library uses.
Actually map1[1] = obj will create pair first