LINUX.ORG.RU

почему move ctor был использован несмотря на throw()?

 ,


1

3

Сабж.

#include <iostream>
#include <vector>
using namespace std;

struct A {
    A() { cout << "ctor" << endl; }
    A(const A& x) { cout << "copy ctor" << endl; }
    A(A&& x) throw() { cout << "move ctor" << endl; }
};

int main()
{
    vector<A> v;
    for (auto i = 0; i < 4; ++i)
    {
        cout << "Item: " << endl;
        cout << "Capacity: " << v.capacity() << endl;
        v.push_back(A());
    }
}

Output:

Item: 
Capacity: 0
ctor
move ctor
Item: 
Capacity: 1
ctor
move ctor
move ctor
Item: 
Capacity: 2
ctor
move ctor
move ctor
move ctor
Item: 
Capacity: 4
ctor
move ctor

Разве vector не обеспечивает strong exception safe guarantee? Ведь в данном случае move ctor мог сломаться и оставить vector в поломанном состоянии.

★★

Последнее исправление: dissident (всего исправлений: 1)

Несмотря на то что использовался move ctor который мог сломаться, vector остался бы в нормальном состоянии.

Я посмотрел стандартную библиотеку и там так:

void push_back(const _Ty& _Val)
{
    // insert element at end, provide strong guarantee
    emplace_back(_Val);
}

void push_back(_Ty&& _Val)
{	
    // insert by moving into element at end, provide strong guarantee
    emplace_back(std::move(_Val));
}
сигнатура emplace_back:
	template<class... _Valty>
		decltype(auto) emplace_back(_Valty&&... _Val)
Весь код, который выделяет память и делает работу, он в emplace_back, а если поломаемся в push_back, то на vector мы никак не повлияем...

fsb4000 ★★★★★
()
Последнее исправление: fsb4000 (всего исправлений: 3)
Ответ на: комментарий от fsb4000

А вообще может я не совсем понял. Добавил copy конструктор с noexcept и стало так:

#include <iostream>
#include <vector>
using namespace std;

struct A {
	A() { cout << "ctor" << endl; }
	A(const A& x) noexcept(true) { cout << "copy ctor" << endl; }
	A(A&& x) noexcept(false) { cout << "move ctor" << endl; }
};

int main()
{
	vector<A> v;
	for (auto i = 0; i < 4; ++i)
	{
		cout << "Item: " << endl;
		cout << "Capacity: " << v.capacity() << endl;
		v.push_back(A());
	}
}
Item:
Capacity: 0
ctor
move ctor
Item:
Capacity: 1
ctor
move ctor
copy ctor
Item:
Capacity: 2
ctor
move ctor
copy ctor
copy ctor
Item:
Capacity: 3
ctor
move ctor
copy ctor
copy ctor
copy ctor

Добавлено: noexcept не влияет, c noexcept(false) у copy ctor, тоже самое...

fsb4000 ★★★★★
()
Последнее исправление: fsb4000 (всего исправлений: 1)
Ответ на: комментарий от fsb4000

«Если сдох, значит гарантия кончилась» :)

annulen ★★★★★
()
Ответ на: комментарий от fsb4000

Да, это я ступил, throw() = noexcept, надо было noexcept(false) действительно.

dissident ★★
() автор топика
Ответ на: комментарий от fsb4000

Сам emplace_back может в случае size > capacity начать переносить элементы и использовать при этом или move noexcept(true) или copy если move noexcept(false).

Я просто тупо ступил и перепутал noexcept(false) со throw().

dissident ★★
() автор топика
Последнее исправление: dissident (всего исправлений: 1)
Ответ на: комментарий от fsb4000

Вот так:

    A(A&& x) noexcept { cout << "move ctor" << endl; }

Выход такой:

Item: 
Capacity: 0
ctor
move ctor
Item: 
Capacity: 1
ctor
move ctor
move ctor
Item: 
Capacity: 2
ctor
move ctor
move ctor
move ctor
Item: 
Capacity: 4
ctor
move ctor

А так:

    A(A&& x) { cout << "move ctor" << endl; }

Вот такой:

Item: 
Capacity: 0
ctor
move ctor
Item: 
Capacity: 1
ctor
move ctor
copy ctor
Item: 
Capacity: 2
ctor
move ctor
copy ctor
copy ctor
Item: 
Capacity: 4
ctor
move ctor

Т.е. вроде как все правильно.

dissident ★★
() автор топика
Последнее исправление: dissident (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.