встроенный конструктор std :: vector

Могу ли я создать вектор, содержащий элементы, которые не могут быть скопированы и не имеют конструктора по умолчанию в C ++ 11?

пример:

#include <iostream>
#include <string>
#include <vector>

struct value {
value() = delete;
~value() = default;

value(value const&) = delete;
value& operator =(value const&) = delete;

explicit value(int i) : i_(i) {}
private:
int i_;
};

int main() {
std::vector<value> v;
v.reserve(10);
for (unsigned i = 0; i < 10; ++i)
v.emplace_back(7);
}

и здесь я хочу создать 10 значений и каждое значение ctor передать целое число 7 …

std::vector< value > v(in-place, 10, 7)

Почему в конструктор std :: vector не была добавлена ​​форма построения размещения C ++ 11

Ошибки вставлены из coliru:

+ g++ -std=c++11 -O2 -Wall -pedantic -pthread main.cpp
In file included from /usr/include/c++/4.8/vector:62:0,
from main.cpp:3:
/usr/include/c++/4.8/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = value; _Args = {value}]’:
/usr/include/c++/4.8/bits/stl_uninitialized.h:75:53:   required from ‘static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<value*> _ForwardIterator = value*; bool _TrivialValueTypes = false]’
/usr/include/c++/4.8/bits/stl_uninitialized.h:117:41:   required from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<value*> _ForwardIterator = value*]’
/usr/include/c++/4.8/bits/stl_uninitialized.h:258:63:   required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = std::move_iterator<value*> _ForwardIterator = value*; _Tp = value]’
/usr/include/c++/4.8/bits/stl_vector.h:1142:29:   required from ‘std::vector<_Tp, _Alloc>::pointer std::vector<_Tp, _Alloc>::_M_allocate_and_copy(std::vector<_Tp, _Alloc>::size_type, _ForwardIterator, _ForwardIterator) [with _ForwardIterator = std::move_iterator<value*> _Tp = value; _Alloc = std::allocator<value> std::vector<_Tp, _Alloc>::pointer = value*; std::vector<_Tp, _Alloc>::size_type = long unsigned int]’
/usr/include/c++/4.8/bits/vector.tcc:75:70:   required from ‘void std::vector<_Tp, _Alloc>::reserve(std::vector<_Tp, _Alloc>::size_type) [with _Tp = value; _Alloc = std::allocator<value> std::vector<_Tp, _Alloc>::size_type = long unsigned int]’
main.cpp:24:17:   required from here
/usr/include/c++/4.8/bits/stl_construct.h:75:7: error: use of deleted function ‘value::value(const value&)’
{ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
^
main.cpp:11:5: error: declared here
value(value const&) = delete;
^

2

Решение

Причина, по которой вы получаете ошибки, заключается в том, что использование emplace_back на std::vector требует, чтобы тип элемента был как минимум MoveConstructible. Это необходимо, если вектор должен расти и перераспределять свои элементы.

Добавить переместить конструктор вам структура, и вы сможете использовать ее в своем коде (реализация по умолчанию будет достаточно для вашего кода).

value(value&&) = default;

Компилятор не будет явно генерировать конструктор перемещения по умолчанию для вашей структуры, как вы объявили свой собственный конструктор копирования, value(value const&) = delete (=delete а также =default считать как пользователь), а также оператор копирования и деструктор.

Для получения дополнительной информации о правилах генерации неявного конструктора перемещения смотрите здесь: Почему по умолчанию нет перемещения-назначения / перемещения-конструктора?


С помощью std::vectorконструктор формы std::vector(size_t count, const T& value) копирует значения в вектор и требует, чтобы тип элемента был CopyConstructible.

3

Другие решения

Да, изменение размера и т. Д. Можно все они обрабатываются с помощью Move вместо конструктора / присваивания копирования, если вы его определили (что бы ни говорил cppreference).

#include <vector>
#include <iostream>

struct value {
int i_;

explicit value(int i) : i_(i)   {std::cout<<"value::value("  <<i_<<")\n"; }
value(value &&src) : i_(src.i_) {std::cout<<"value::value(&&"<<i_<<")\n"; }
value(value const&) = delete;
value& operator=(value const&) = delete;
value& operator=(value &&src) {
i_ = src.i_;
std::cout << "value::=(&&" << i_ << ")\n";
return *this;
}
value() = delete;
};

int main() {
std::vector<value> v;
v.reserve(1);
v.emplace_back(1);
v.emplace_back(2);
v.emplace_back(3);
}

работает отлично:

value::value(1)   <-- emplace_back(1)
value::value(2)
value::value(&&1) <-- emplace_back(2) inc. resize & move 1
value::value(3)
value::value(&&1)
value::value(&&2) <-- emplace_back(3) inc. resize & move 1,2

Мотивация для требования

До поддержки перемещения, если бы элементы вектора не были копируемыми, он не смог бы изменить свой размер (или стереть элементы, или выполнить довольно много его интерфейса).

2

Да, вы можете поместить объекты, которые нельзя копировать или конструировать по умолчанию, в vector в C ++ 11, если они являются подвижными:

#include <iostream>
#include <string>
#include <vector>

struct value {
value() = delete;
~value() = default;

value(value const&) = delete;
value& operator =(value const&) = delete;

// Move construction and assignment
value(value&&) = default;
value& operator =(value&&) = default;

explicit value(int i) : i_(i) {}
private:
int i_;
};

int main() {
std::vector<value> v;
v.reserve(10);
for (unsigned i = 0; i < 10; ++i)
v.emplace_back(7);
}

Но вы не можете использовать конструктор, который заполняет такой вектор копиями заданного значения — так как значения не могут быть скопированы. Точно так же вы не можете вырастить вектор таких объектов с resize,

1

Напишите конструктор перемещения и затем используйте emplace_back:

struct value
{
...

value(value && obj) : i_(obj.i_)
{
}

or

value(value && obj) = default;

...
};

std::vector<value> v;

for (int i=0; i<10; i++)
v.emplace_back(7);
0
По вопросам рекламы [email protected]