Почему вектор копирует данные при расширении?
От: toro  
Дата: 23.10.18 14:18
Оценка: 10 (1)
День добрый. Напомните, пожалуйста, в чем причина такого поведения?

class Test
{
    std::string a;

public:
    Test (const char * pa)
    {
        a = pa;
        std::cout << "ctor\n";
    }

    Test (const Test & t)
    {
        a = t.a;
        std::cout << "copy ctor: " << a << "\n";
    }

    Test (Test && t)
    {
        a = std::move (t.a);
        std::cout << "move ctor: " << a << "\n";
    }

    Test & operator = (const Test & t)
    {
        a = t.a;
        std::cout << "copy =: " << a << "\n";
        return *this;
    }

    Test & operator = (Test && t)
    {
        a = std::move (t.a);
        std::cout << "move =: " << a << "\n";
        return *this;
    }

};

int main ()
{
    std::vector <Test> v;

    Test t1("1"), t2("a"), t3("10");

    v.emplace_back (std::move (t1));
    v.emplace_back (std::move (t2));
    v.emplace_back (std::move (t3));

     return 0;
}

output:

ctor
ctor
ctor
move ctor: 1
move ctor: a
copy ctor: 1
move ctor: 10
copy ctor: 1
copy ctor: a


Если же в классе закрыть копирование, то все начинает муваться:

class Test
{
    std::string a;

public:
    Test (const char * pa)
    {
        a = pa;
        std::cout << "ctor\n";
    }

    Test (const Test & t) = delete;
    Test & operator = (const Test & t) = delete;

    Test (Test && t)
    {
        a = std::move (t.a);
        std::cout << "move ctor: " << a << "\n";
    }

    Test & operator = (Test && t)
    {
        a = std::move (t.a);
        std::cout << "move =: " << a << "\n";
        return *this;
    }

};

int main 
{
    // такой же
}


output:

ctor
ctor
ctor
move ctor: 1
move ctor: a
move ctor: 1
move ctor: 10
move ctor: 1
move ctor: a


Соответственно, почему, когда вектор расширяется, он в новосозданный буфер из старого копирует данные, а не мувает?
Если б вызывалось std::move из старого в новый, то вызывались бы конструкторы перемещения, что легко проверить:


class Test
{
    // такой же, как в первом примере, с доступными к-рами копирования
};


int main ()
{
    std::vector <Test> v;

    Test t1 ("1"), t2 ("a"), t3 ("10");

    v.emplace_back (std::move (t1));
    v.emplace_back (std::move (t2));
    v.emplace_back (std::move (t3));


    std::vector <Test> v2;
    v2.reserve (3);
    v2.emplace (v2.begin (), std::move (v[0]));

     return 0;
}

output:

ctor
ctor
ctor
move ctor: 1
move ctor: a
copy ctor: 1
move ctor: 10
copy ctor: 1
copy ctor: a
move ctor: 1       <---
Отредактировано 23.10.2018 14:23 toro . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.