5 Replies - 1112 Views - Last Post: 02 November 2019 - 07:13 AM Rate Topic: ****- 1 Votes

#1 darek9576   User is offline

  • D.I.C Lover

Reputation: 204
  • View blog
  • Posts: 1,737
  • Joined: 13-March 10

Why does vector not call a move constructor?

Posted 31 October 2019 - 04:42 AM

I am playing with move semantics and i do not understand why the vector would call a copy constructor instead of a move constructor when it has to resize itself and move already existing objects within the vector. It's slower. Is there something i am missing and the vector is not able to do it for some reason?

class Person
{
public:
	Person(const std::string& firstName, const std::string& lastName) : _firstName(new std::string(firstName)), _lastName(new std::string(lastName))
	{
		std::cout << "Constructor called" << std::endl;
	}

	~Person()
	{
		std::cout << "Destructor called for: " << *_firstName << ", " << *_lastName << std::endl;
		delete _firstName;
		delete _lastName;
	}

	Person(const Person& other) //copy constructor
	{
		std::cout << "Copy constructor called" << std::endl;
		_firstName = new std::string(*other._firstName);
		_lastName = new std::string(*other._lastName);
	}

	Person(Person&& src)
	{
		std::cout << "Move constructor called" << std::endl;
		_firstName = src._firstName;
		_lastName = src._lastName;

		//clear the source
		src._firstName = 0;
		src._lastName = 0;
	}

	Person& operator=(const Person& rhs)
	{
		std::cout << "Copy assignment operator called" << std::endl;
		if (this != &rhs)
		{
			delete _firstName;
			delete _lastName;

			_firstName = new std::string(*rhs._firstName);
			_lastName = new std::string(*rhs._lastName);
		}

		return *this;
	}


	Person& operator=(Person&& rhs)
	{
		std::cout << "Move assignment operator called" << std::endl;
		if (this != &rhs)
		{
			delete _firstName;
			delete _lastName;

			_firstName = rhs._firstName;
			_lastName = rhs._lastName;

			rhs._firstName = 0;
			rhs._lastName = 0;
		}

		return *this;
	}

protected:	//visible in derived classes if public inheritance is used
	std::string* _firstName;
	std::string* _lastName;
};


void InsertIntoVector()
{
	std::vector<Person> p;
	std::cout << "Size: " << p.size() << ", Capacity: " << p.size() << std::endl;


	Person a("A", "A");
	p.push_back(a);
	std::cout << "Size: " << p.size() << ", Capacity: " << p.capacity() << std::endl;

	Person b("B", "B");
	p.push_back(B)/>;
	std::cout << "Size: " << p.size() << ", Capacity: " << p.capacity() << std::endl;

	std::cout << "\n\n";
	Person c("C", "C");
	p.push_back(c);
	std::cout << "Size: " << p.size() << ", Capacity: " << p.capacity() << std::endl;

}




Output:

Size: 0, Capacity: 0
Constructor called
Copy constructor called
Size: 1, Capacity: 1
Constructor called
Copy constructor called       //<--- why not move constructor
Copy constructor called
Destructor called for: A, A
Size: 2, Capacity: 2


Constructor called
Copy constructor called    // <--- why not move constructor
Copy constructor called    // <-- why not move constructor
Copy constructor called
Destructor called for: A, A
Destructor called for: B, B
Size: 3, Capacity: 3



Hope someone can explain that to me.

Is This A Good Question/Topic? 1
  • +

Replies To: Why does vector not call a move constructor?

#2 Skydiver   User is offline

  • Code herder
  • member icon

Reputation: 7095
  • View blog
  • Posts: 24,113
  • Joined: 05-May 12

Re: Why does vector not call a move constructor?

Posted 31 October 2019 - 07:10 AM

Did you see the answer on StackOverflow?

Short answer the move constructor needs to be declared noexcept if you want it to be called by std::vector as per the C++11 standard. See the SO link above for the long answer of why the standard requires it.
Was This Post Helpful? 1
  • +
  • -

#3 jimblumberg   User is offline

  • member icon

Reputation: 5765
  • View blog
  • Posts: 17,654
  • Joined: 25-December 09

Re: Why does vector not call a move constructor?

Posted 31 October 2019 - 08:47 AM

Why are you using those std::string pointers? A std::string is already a dynamically allocated type so there is really no need to manually dynamically allocate memory for that type.

Jim
Was This Post Helpful? 1
  • +
  • -

#4 Skydiver   User is offline

  • Code herder
  • member icon

Reputation: 7095
  • View blog
  • Posts: 24,113
  • Joined: 05-May 12

Re: Why does vector not call a move constructor?

Posted 31 October 2019 - 09:37 AM

Probably a Java to C++ transliteration.
Was This Post Helpful? 1
  • +
  • -

#5 darek9576   User is offline

  • D.I.C Lover

Reputation: 204
  • View blog
  • Posts: 1,737
  • Joined: 13-March 10

Re: Why does vector not call a move constructor?

Posted 02 November 2019 - 05:06 AM

Thanks. noexcept does the trick. No, i am just trying to learn how to write code that does not leak.
Was This Post Helpful? 0
  • +
  • -

#6 Skydiver   User is offline

  • Code herder
  • member icon

Reputation: 7095
  • View blog
  • Posts: 24,113
  • Joined: 05-May 12

Re: Why does vector not call a move constructor?

Posted 02 November 2019 - 07:13 AM

And so to prevent the leaks, avoid using pointers in the first place as Jim suggested above. If you had declared:
class Person
{
public:
    Person(const std::string & first, const std::string & last)
        : _firstName(first)
        , _lastName(last)
    {
    }

private:
    std::string _firstName;
    std::string _lastName;
};


then the memory for the strings within the class would be deallocated when the Person instance freed.

If you must use pointers, prefer to use the smart pointer classes: shared_ptr and unique_ptr. See A beginner's look at smart pointers in modern C++
Was This Post Helpful? 1
  • +
  • -

Page 1 of 1