Skip to content

For Node<T> move constructor, T copy constructor is called when the move constructor is not defined but the move assignment operator is defined. #345

@AryanGitHub

Description

@AryanGitHub

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:

  1. 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;
}
  1. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Priority:CriticalPriority Label for Critical IssuebugSomething isn't workingcoresomething about coreperformancePerformance issue

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions