move constructor / move assignment
Feb 5, 2021 at 9:42pm Feb 5, 2021 at 9:42pm UTC
Recently I have been practicing the different types of constructors and assingment operators. I am now doing the move constructor and assignment, and I think I have it somewhat correct, but I can not find any examples that have any class variables apart from the pointer that needs to be moved, so I am not sure if i am doing it correct. Is my move constructor and assignment correct? I am most unsure about the std::move in the assignment, im not sure if this is the correct way of doing it.
When I am testing the program it is running correctly, but ive done things in the past that worked but wasnt put together right, and I want to be learning the correct way. So any help is appreciated.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
#pragma once
#include <iostream>
#include "engine.h"
using std::string;
class vehicle
{
private :
string* ptr_Name;
string colour;
int doors;
engine Engine;
public :
//constructor
vehicle(string P_name, string& P_colour, int & P_doors, engine P_engine) : ptr_Name(new string(P_name)), colour(P_colour), doors(P_doors), Engine(P_engine) {}
//destructor
~vehicle() { delete ptr_Name; }
//copy constructor
vehicle(const vehicle& obj) : ptr_Name(new string(obj.getName())), colour(obj.colour), doors(obj.doors), Engine(obj.Engine) {}
//copy assignment
vehicle& operator = (const vehicle& obj)
{
if (this != &obj)
{
delete ptr_Name;
ptr_Name = new string(obj.getName());
colour = obj.getColour();
doors = obj.getDoors();
Engine = obj.Engine;
}
return *this ;
}
//move constructor
vehicle(vehicle&& obj) : ptr_Name(obj.ptr_Name), colour(std::move(obj.colour)), doors(std::move(obj.doors)), Engine(std::move(obj.Engine))
{
obj.ptr_Name = nullptr ;
}
//move assignment
vehicle& operator = (vehicle&& obj)
{
delete ptr_Name;
ptr_Name = obj.ptr_Name;
obj.ptr_Name = nullptr ;
*this = std::move(obj);
return *this ;
}
string getName() const ;
string getColour() const ;
int getDoors() const ;
engine getEngine() const ;
void getDetails() const ;
};
Feb 6, 2021 at 5:12am Feb 6, 2021 at 5:12am UTC
> Is my move constructor and assignment correct? I am most unsure about the std::move in
> the assignment, im not sure if this is the correct way of doing it.
Your move assignment operator would cause an infinite loop.
1 2 3 4 5 6 7 8 9
//move assignment
vehicle& operator = (vehicle&& obj)
{
delete ptr_Name;
ptr_Name = obj.ptr_Name;
obj.ptr_Name = nullptr ;
*this = std::move(obj); // **** this calls the move assignment operator again
return *this ;
}
Ideally, the move operations should be non-throwing operations.
> I can not find any examples that have any class variables apart from the pointer that needs to be moved
We could use a member object of a user-defined type (that noisily announces when it is copied, moved etc.) to test out our code. For example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
#include <iostream>
#include <string>
#include <type_traits>
#include <vector>
struct noisy_str
{
noisy_str( const char * cstr ) : str(cstr) { print("constructor" ) ; }
noisy_str( std::string str = {} ) : str( std::move(str) ) { print( "constructor" ) ; }
noisy_str( const noisy_str& that ) : str(that.str) { print( "copy constructor" ) ; }
noisy_str( noisy_str&& that ) noexcept ( std::is_nothrow_move_constructible<std::string>::value )
: str( std::move(that.str) ) { print( "move constructor" ) ; }
noisy_str& operator = ( const noisy_str& that )
{ str = that.str ; print( "copy assignment" ) ; return *this ; }
noisy_str& operator = ( noisy_str&& that ) noexcept ( std::is_nothrow_move_assignable<std::string>::value )
{ str = std::move(that.str) ; print( "move assignment" ) ; return *this ; }
~noisy_str() { print( "destructor" ) ; }
operator const std::string& () const noexcept { return str ; }
operator std::string& () { return str ; }
std::string str ;
std::ostream& print( const char * oper ) const
{ return std::cout << "noisy_str::" << oper << '\n' ; }
};
struct vehicle
{
vehicle( std::string str = "anonymous" ) : name_( std::move(str) ) {}
vehicle( const vehicle& that ) : name_( that.name_ ) {}
vehicle( vehicle&& that ) noexcept ( std::is_nothrow_move_constructible<noisy_str>::value )
: name_( std::move(that.name_) ) {}
vehicle& operator = ( const vehicle& that ) { name_ = that.name_ ; return *this ; }
vehicle& operator = ( vehicle&& that ) noexcept ( std::is_nothrow_move_assignable<noisy_str>::value )
{ name_ = std::move(that.name_) ; return *this ; }
~vehicle() = default ;
const std::string& name() const noexcept { return name_ ; }
noisy_str name_ ;
};
int main()
{
{
std::cout << "construct v: " ;
vehicle v { "1234" } ;
std::cout << "\ncopy construct v2: " ;
vehicle v2(v) ;
std::cout << "\nmove construct v3: " ;
vehicle v3( std::move(v2) ) ;
std::cout << "\ncopy assignment: " ;
v = v3 ;
std::cout << "\nmove assignment: " ;
v3 = std::move(v) ;
std::cout << "\ndestroy v3, v2, v1\n" ;
}
std::cout << "\nconstruct vector of three vehicles\n" ;
std::vector<vehicle> vec(3) ;
std::cout << "\nmove the vehicles in the vector\n" ;
// nothrow_move_constructible, so the vector should use the non-throwing move constructor to move the items
vec.reserve( vec.capacity() + 1 ) ;
std::cout << "\ndestroy vector of three vehicles\n" ;
}
http://coliru.stacked-crooked.com/a/a3454a5aa34113a1
https://rextester.com/UMXG36332
Topic archived. No new replies allowed.