Copy constructor, move constructor, copy assignment operator, move assignment operator

      Comments Off on Copy constructor, move constructor, copy assignment operator, move assignment operator

Mặc định thì trình biên dịch đã tạo cho ta default copy (move) constructor và default copy(move) assignment operator.
Mấy cái default này chỉ là shallow copy thôi( copy nông). Nếu class của mình có con trỏ thì phải tự viết hết nếu không sẽ sai logic.

Khi nào thì gọi copy(move) constructor khi nào thì gọi copy(move) assignment operator.
Link: https://www.geeksforgeeks.org/copy-constructor-vs-assignment-operator-in-c/


#include<iostream>
#include<stdio.h>
 
using namespace std;
 
class Test
{
public:
   Test() {}
   Test(const Test &t)
   {
      cout<<"Copy constructor called "<<endl;
   }
   Test& operator = (const Test &t)
   {
      cout<<"Assignment operator called "<<endl;
   }
};
 
int main()
{
  Test t1, t2;
  t2 = t1;  // calls assignment operator, same as "t2.operator=(t1);"
  Test t3 = t1;  // calls copy constructor, same as "Test t3(t1);"
  getchar();
  return 0;
}

Tương tự như move semantic
Dưới đây là ví dụ full

/* Write copy constructor, move constructor, copy assignment operator,
move assignment operator for the following class

class DirectorySearchResult {
public:
	DirectorySearchResult(
	std::vector<std::string> const& files,
	size_t attributes,
	SearchQuery const* query)
	: files(files),
	attributes(attributes),
	query(new SearchQuery(*query))
	{ }

	~DirectorySearchResult() { delete query; }

	private:
	std::vector<std::string> files;
	size_t attributes;
	SearchQuery* query;
};
*/

#include <iostream>
#include<vector>

class SearchQuery {
public:
	int value;
	SearchQuery() {
		value = 10;
		//std::cout << "SearchQuery constructor\n";
	}
	~SearchQuery() {
		//std::cout << "~SearchQuery\n";
	}
};

class DirectorySearchResult {
public:
	DirectorySearchResult(
		std::vector<std::string> const& files,
		size_t attributes,
		SearchQuery const* query)
		: files(files),
		attributes(attributes),
		query(new SearchQuery(*query))
	{
		//std::cout << "DirectorySearchResult constructor\n";
	}
	
	//Copy constructor
	DirectorySearchResult(DirectorySearchResult const &o) {
		attributes = o.attributes;
		files = o.files;
		query = new SearchQuery(*o.query);
		std::cout << "copy constructor\n";
	}
	//Move constructor
	DirectorySearchResult(DirectorySearchResult && other) :
		attributes(other.attributes), files(std::move(other.files)), query(other.query) {
		other.query = nullptr;
		std::cout << "Move constructor\n";
	}
	//Copy assignment operator
	DirectorySearchResult& operator=(const DirectorySearchResult& other) {
		files = other.files;
		attributes = other.attributes;
		delete query;
		query = other.query? new SearchQuery(*other.query):nullptr;
		std::cout << "Copy assignment operator\n";
		return *this;
	}
	//Move assignment operator
    DirectorySearchResult& operator=(DirectorySearchResult && other) {
		attributes = other.attributes;
		files = std::move(other.files);
		delete query;
		query = other.query;
		other.query = nullptr;
		std::cout << "Move operator\n";
		return *this;
	}
	~DirectorySearchResult() { 
		//delete query;
		//std::cout << "~DirectorySearchResult\n";
	}

private:
	std::vector<std::string> files;
	size_t attributes;
	SearchQuery* query;
};

DirectorySearchResult f(DirectorySearchResult a) {
	return a;
}

int main() {
	const SearchQuery* query = new SearchQuery();
	DirectorySearchResult d1 ({ "file1","file2" }, 10, query);
	DirectorySearchResult d2(d1); // copy constructor
	d2= d1; // copy assignment operator
	d2 = f(d1); // Move assignment operator
	DirectorySearchResult d3 = f(d2); // fist copy constructor and then move constructor.
	return 0;
}

Move constructor

Implicitly-declared move constructor

If no user-defined move constructors are provided for a class type (struct, class, or union), and all of the following is true:

Deleted implicitly-declared move constructor

The implicitly-declared or defaulted move constructor for class T is defined as deleted if any of the following is true:

  • T has non-static data members that cannot be moved (have deleted, inaccessible, or ambiguous move constructors);
  • T has direct or virtual base class that cannot be moved (has deleted, inaccessible, or ambiguous move constructors);
  • T has direct or virtual base class with a deleted or inaccessible destructor;
  • T is a union-like class and has a variant member with non-trivial move constructor;

 

move_assignment

Implicitly-declared move assignment operator

If no user-defined move assignment operators are provided for a class type (struct, class, or union), and all of the following is true:

  • there are no user-declared copy constructors;
  • there are no user-declared move constructors;
  • there are no user-declared copy assignment operators;
  • there are no user-declared destructors;

Deleted implicitly-declared move assignment operator

The implicitly-declared or defaulted move assignment operator for class T is defined as deleted if any of the following is true:

  • T has a non-static data member that is const;
  • T has a non-static data member of a reference type;
  • T has a non-static data member that cannot be move-assigned (has deleted, inaccessible, or ambiguous move assignment operator);
  • T has direct or virtual base class that cannot be move-assigned (has deleted, inaccessible, or ambiguous move assignment operator);

copy_constructor

Implicitly-declared copy constructor

If no user-defined copy constructors are provided for a class type (struct, class, or union), the compiler will always declare a copy constructor as a non-explicit inline public member of its class. This implicitly-declared copy constructor has the form T::T(const T&) if all of the following are true:

  • each direct and virtual base B of T has a copy constructor whose parameters are const B& or const volatile B&;
  • each non-static data member M of T of class type or array of class type has a copy constructor whose parameters are const M& or const volatile M&.

Deleted implicitly-declared copy constructor

The implicitly-declared copy constructor for class T is undefined if any of the following conditions are true: (until C++11)
The implicitly-declared or defaulted copy constructor for class T is defined as deleted if any of the following conditions are true: (since C++11)
  • T has non-static data members that cannot be copied (have deleted, inaccessible, or ambiguous copy constructors);
  • T has direct or virtual base class that cannot be copied (has deleted, inaccessible, or ambiguous copy constructors);
  • T has direct or virtual base class with a deleted or inaccessible destructor;

copy_assignment

Implicitly-declared copy assignment operator

If no user-defined copy assignment operators are provided for a class type (struct, class, or union), the compiler will always declare one as an inline public member of the class. This implicitly-declared copy assignment operator has the form T& T::operator=(const T&) if all of the following is true:

  • each direct base B of T has a copy assignment operator whose parameters are B or const B& or const volatile B&;
  • each non-static data member M of T of class type or array of class type has a copy assignment operator whose parameters are M or const M& or const volatile M&.

Deleted implicitly-declared copy assignment operator

A implicitly-declared copy assignment operator for class T is defined as deleted if any of the following is true:

  • T has a user-declared move constructor;
  • T has a user-declared move assignment operator.