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.
Related
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.
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 am playing around with std::function and std::bind to understand how arguments are copied around and if I can save some of the copy operations.
I understand that when using std::bind, the arguments are passed by value and not reference (unless std::ref is specified). However, when I run the following snippet, the copy constructor is invoked twice. Can someone explain why?
struct token
{
static int i;
int code;
token()
: code(i++)
{
cout << __FUNCTION__ << ": " << code << endl;
}
virtual ~token()
{
cout << __FUNCTION__ << endl;
}
token (token const & other)
: code (other.code)
{
cout << "copy ctor: " << code << endl;
}
// update -- adding a move ctor
token (token const && other)
: code (std::move(other.code))
{
cout << "move ctor: " << code << endl;
}
// update -- end
void boo() const
{
cout << __FUNCTION__ << ": " << code << endl;
}
};
void call_boo(token const & t)
{
t.boo();
}
int main()
{
token t2;
cout << "default" << endl;
std::function< void () >(std::bind(&call_boo, t2));
cout << "ref" << endl;
std::function< void () >(std::bind(&call_boo, std::ref(t2)));
cout << "move" << endl;
std::function< void () >(std::bind(&call_boo, std::move(t2)));
cout << "end" << endl;
return 0;
}
When run, this produces the following output:
token: 1
default
// Without move ctor
// copy ctor: 1 // Makes sense. This is the passing by value.
// copy ctor: 1 // Why does this happen?
// With move ctor
copy ctor: 1
move ctor: 1
~token
~token
ref // No copies. Once again, makes sense.
move
// Without move ctor
// copy ctor: 1
// copy ctor: 1
// With move ctor
move ctor: 1
move ctor: 1
~token
~token
end
~token
Parameters for this constructor of std::function are always copied, so a copy of the bind object (which itself has a copy of your token object) is created inside the std::function.
http://en.cppreference.com/w/cpp/utility/functional/function/function
template< class F >
function( F f );
5) Initializes the target with a copy of f. If f is a null pointer to function or null pointer to member, *this will be empty after the call. This constructor does not participate in overload resolution unless f is Callable for argument types Args... and return type R. (since C++14)
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
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).