<<< The move constructor | Index | A better approach: use library string >>> |
Here is the final version of our struct that allocates/deallocates memory dynamically:
#include <cstdlib> #include <iostream> #include <cstring> struct Rectangle { int width; // member variable int height; // member variable char* ptr_name; Rectangle() : width( 1 ), height( 1 ), ptr_name( nullptr ) { std::cout << "DEBUG default constructor " << __FUNCTION__ << '\n'; set_name( "UNKNOWN" ); } Rectangle( char const* ptr_name_, int width_ ) : width( width_ ), height( width_ ), ptr_name( nullptr ) { set_name( ptr_name_ ); } Rectangle( char const* ptr_name_, int width_ , int height_ ) : width( width_ ), height( height_ ), ptr_name( nullptr ) { set_name( ptr_name_ ); } Rectangle( Rectangle const& another_rectangle_ ) : width( another_rectangle_.width ), height( another_rectangle_.height ), ptr_name( nullptr ) { std::cout << "DEBUG copy constructor " << __FUNCTION__ << '\n'; set_name( another_rectangle_.ptr_name ); } ~Rectangle() { if ( ptr_name ) delete[] ptr_name; ptr_name = nullptr; } // C++ overloaded assignment operator: Rectangle& operator=( Rectangle const& another_rectangle_ ) { std::cout << "DEBUG assignment " << __FUNCTION__ << '\n'; if ( this == &another_rectangle_ ) { // avoid assignment to self: return *this; } width = another_rectangle_.width; height = another_rectangle_.height; set_name( another_rectangle_.ptr_name ); return *this; } // move constructor Rectangle( Rectangle&& another_rectangle_ ) { std::cout << "DEBUG move constructor " << __FUNCTION__ << '\n'; width = another_rectangle_.width; height = another_rectangle_.height; ptr_name = another_rectangle_.ptr_name; another_rectangle_.ptr_name = nullptr; } void set_name( char const* ptr_name_ ) { if ( ptr_name ) delete[] ptr_name; int name_length = strlen( ptr_name_ ) + 1; ptr_name = new char[ name_length ]; strncpy( ptr_name, ptr_name_, name_length ); } char const* get_name() const { return ptr_name; } void set_dimensions( int width_ , int height_ ) { width = width_; height = height_; } int area() const { return ( width * height ); } }; void normalize( Rectangle* ptr_rect ) { ptr_rect->set_dimensions( 1, 1 ); } Rectangle create_rectangle() { Rectangle temp; temp.set_name( "FACTORY CREATED" ); return temp; } int main() { Rectangle rect( "first", 333, 222 ); Rectangle rect2 = rect; // make a deep copy rect2.set_name( "second" ); std::cout << "rectangle width: " << rect.width << '\n'; std::cout << "rectangle height: " << rect.height << '\n'; std::cout << "rectangle area: " << rect.area() << '\n'; std::cout << "rectangle name: " << rect.get_name() << '\n' << '\n'; rect = rect2; // shallow assignment std::cout << "rectangle width: " << rect2.width << '\n'; std::cout << "rectangle height: " << rect2.height << '\n'; std::cout << "rectangle area: " << rect2.area() << '\n'; std::cout << "rectangle name: " << rect2.get_name() << '\n' << '\n'; rect2 = create_rectangle(); std::cout << "rectangle width: " << rect2.width << '\n'; std::cout << "rectangle height: " << rect2.height << '\n'; std::cout << "rectangle area: " << rect2.area() << '\n'; std::cout << "rectangle name: " << rect2.get_name() << '\n' << '\n'; system( "pause" ); return 0; }
<<< The move constructor | Index | A better approach: use library string >>> |