-
Notifications
You must be signed in to change notification settings - Fork 139
Description
Describe the bug
For Node<T>, when Node<T>::Node(const std::string& id, T&& data) is invoked for T, where T's move constructor is not defined but T's move assignment operator is defined, the T's copy constructor is invoked.
Hence where a move operation can be used, a copy operation is used.
A move operation is of constant time complexity, whereas a copy operation is of linear time complexity
To Reproduce (Minimal Reproducable Example)
Steps to reproduce the behavior:
- Compile the given below code.
#include <CXXGraph.hpp>
#include <memory>
struct obj {
public:
std::string str;
obj()
{
std::cout << "default constructor used" << std::endl;
}
obj(std::string input_str)
: str (input_str)
{
std::cout << "parameterised constructor used" << std::endl;
}
obj(const obj& copySource)
{
this->str = copySource.str;
std::cout << "copy constructor" << std::endl;
}
/*
obj(obj&& moveSource)
{
this->str = std::move(moveSource.str);
std::cout << "move constructor" << std::endl;
}*/
void operator= (const obj& source)
{
std::cout << "copy assignment operator called" << std::endl;
this->str = source.str;
}
void operator= (obj&& source)
{
std::cout << "move assignment operator called" << std::endl;
this->str = std::move(source.str);
}
~obj()
{
std::cout << "destructor called" << std::endl;
}
};
int main() {
CXXGraph::Node<obj> obj_node_0("obj_node_0" ,obj("Hello,World!"));
return 0;
}- Output displays the usage of the copy constructor
Observed behavior
The output uses a copy constructor.
parameterised constructor used
default constructor used
copy constructor
move assignment operator called
move assignment operator called
destructor called
destructor called
destructor called
Expected behavior
The output should only use the move assignment operator.
parameterised constructor used
default constructor used
move assignment operator called
destructor called
destructor called
Reason it happened
in Node<T>::Node(const std::string& id, T&& data) a std::swap() is used.
According to cpprefrence, std::swap() uses move constructor and move assignment operator both.
So when move constructor is not defined, it shifts back to copy constructor.
hence, defeating the purpose of move.
How to resolve?
Use std::move() in Node<T>::Node(const std::string& id, T&& data) instead, so even only if move assignment operator is defined, move can take place.
Thanks.