我可以创建包含不可复制元素且在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)
为什么不将C ++ 11放置构造表单添加到此std :: vector构造函数
从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;
^
答案 0 :(得分:3)
您遇到错误的原因是在emplace_back
上使用std::vector
要求元素类型至少为 MoveConstructible 。如果向量需要增长并重新分配其元素,则需要这样做。
将移动构造函数添加到您的结构中,您将能够在代码中使用它(默认实现将足以满足您的代码)。
value(value&&) = default;
编译器不会隐式生成结构的默认移动构造函数,因为您声明了自己的复制构造函数,value(value const&) = delete
(=delete
和=default
计数作为用户声明的),以及复制赋值运算符和析构函数。
有关隐式移动构造函数生成规则的更多信息,请查看此处:Why no default move-assignment/move-constructor?
使用std::vector
形式std::vector(size_t count, const T& value)
的构造函数将值复制到向量中,并要求元素类型为 CopyConstructible 。
答案 1 :(得分:2)
是的,调整大小等可以全部用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 :(得分:1)
是的,如果它们是可移动的,你可以将不可复制或默认构造的对象放在C ++ 11的vector
中:
#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
生成此类对象的向量。
答案 3 :(得分:0)
编写移动构造函数,然后使用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);