std::vector 不使用具有 noexcept move 构造的对象调用 move 构造函数
std::vector doesn't call move constructor with objects with noexcept move constructs
我最近一直在努力使用移动和复制构造函数,似乎无法自己找到遮阳棚。
结构相当简单。一个 class OWUP,其中包含一个 std::unique_ptr 到一个对象(在本例中是一个 int),一个 class 一个是 OWUP 的 std::vector 和 [=26 的简单包装器=] Two 是 One 的简单包装器 std::vector。
#include <memory>
#include <vector>
class OWUP {
public:
OWUP()
: data(nullptr)
{ }
OWUP(const OWUP &) = delete;
OWUP &operator=(const OWUP &) = delete;
OWUP(OWUP &&) noexcept = default;
OWUP &operator=(OWUP &&) noexcept = default;
std::unique_ptr<int> data;
};
class One {
public:
One(std::size_t numof_datas)
: datas(numof_datas)
{ }
One(const One &) = delete;
One &operator=(const One &) = delete;
One(One &&) noexcept = default;
One &operator=(One &&) noexcept = default;
std::vector<OWUP> datas;
};
class Two {
public:
Two(std::size_t numof_ones, std::size_t num_of_datas)
: ones(numof_ones, One(num_of_datas))
{ }
Two(const Two &) = delete;
Two &operator=(const Two &) = delete;
Two(Two &&) noexcept = default;
Two &operator=(Two &&) noexcept = default;
std::vector<One> ones;
};
代码得到如下错误代码g++ -std=c++14 example.cpp
In file included from /usr/include/c++/7.3.1/memory:64:0,
from example.cpp:1:
/usr/include/c++/7.3.1/bits/stl_construct.h: In instantiation of 'void std::_Construct(_T1*, _Args&& ...) [with _T1 = One; _Args = {const One&}]':
/usr/include/c++/7.3.1/bits/stl_uninitialized.h:210:18: required from 'static _ForwardIterator std::__uninitialized_fill_n<_TrivialValueType>::__uninit_fill_n(_ForwardIterator, _Size, const _Tp&) [with _ForwardIterator = One*; _Size = long unsigned int; _Tp = One; bool _TrivialValueType = false]'
/usr/include/c++/7.3.1/bits/stl_uninitialized.h:255:17: required from '_ForwardIterator std::uninitialized_fill_n(_ForwardIterator, _Size, const _Tp&) [with _ForwardIterator = One*; _Size = long unsigned int; _Tp = One]'
/usr/include/c++/7.3.1/bits/stl_uninitialized.h:366:39: required from '_ForwardIterator std::__uninitialized_fill_n_a(_ForwardIterator, _Size, const _Tp&, std::allocator<_Tp2>&) [with _ForwardIterator = One*; _Size = long unsigned int; _Tp = One; _Tp2 = One]'
/usr/include/c++/7.3.1/bits/stl_vector.h:1337:33: required from 'void std::vector<_Tp, _Alloc>::_M_fill_initialize(std::vector<_Tp, _Alloc>::size_type, const value_type&) [with _Tp = One; _Alloc = std::allocator<One>; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::value_type = One]'
/usr/include/c++/7.3.1/bits/stl_vector.h:298:27: required from 'std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>::size_type, const value_type&, const allocator_type&) [with _Tp = One; _Alloc = std::allocator<One>; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::value_type = One; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<One>]'
example.cpp:40:39: required from here
/usr/include/c++/7.3.1/bits/stl_construct.h:75:7: error: use of deleted function 'One::One(const One&)'
{ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
example.cpp:29:3: note: declared here
One(const One &) = delete;
^~~
我已经尽力强制它使用移动构造函数。我还尝试使用 std::move 创建自己的移动构造函数,但这导致了相同的编译错误。我知道 std::vector 测试 move_if_noexcept(),但无法找出原因。我做错了什么?
因为问题出在这里:
Two(std::size_t numof_ones, std::size_t num_of_datas)
: ones(numof_ones, One(num_of_datas))
{ }
你不能从你在这里创建的 One
移动,你真的需要从它复制 numof_ones
次。
不幸的是,如果 One
没有默认构造函数或复制构造函数,就没有简单的方法来构造大小为 numof_ones
的 std::vector<One>
。您选择的构造函数将您赋予它的单个值 numof_ones
份 复制到向量的每个元素中。
最简单的解决方案可能是不在构造函数初始化列表中初始化 ones
,而是在构造函数的主体中初始化它:
Two(std::size_t numof_ones, std::size_t num_of_datas) {
ones.reserve(numof_ones);
for (size_t i = 0; i != numof_ones; ++i) {
ones.emplace_back(num_of_datas);
}
}
(从技术上讲,您可能会使用带有两个迭代器并提供您自己的自定义迭代器的 std::vector
构造函数,但这可能不值得付出努力)。
我最近一直在努力使用移动和复制构造函数,似乎无法自己找到遮阳棚。 结构相当简单。一个 class OWUP,其中包含一个 std::unique_ptr 到一个对象(在本例中是一个 int),一个 class 一个是 OWUP 的 std::vector 和 [=26 的简单包装器=] Two 是 One 的简单包装器 std::vector。
#include <memory>
#include <vector>
class OWUP {
public:
OWUP()
: data(nullptr)
{ }
OWUP(const OWUP &) = delete;
OWUP &operator=(const OWUP &) = delete;
OWUP(OWUP &&) noexcept = default;
OWUP &operator=(OWUP &&) noexcept = default;
std::unique_ptr<int> data;
};
class One {
public:
One(std::size_t numof_datas)
: datas(numof_datas)
{ }
One(const One &) = delete;
One &operator=(const One &) = delete;
One(One &&) noexcept = default;
One &operator=(One &&) noexcept = default;
std::vector<OWUP> datas;
};
class Two {
public:
Two(std::size_t numof_ones, std::size_t num_of_datas)
: ones(numof_ones, One(num_of_datas))
{ }
Two(const Two &) = delete;
Two &operator=(const Two &) = delete;
Two(Two &&) noexcept = default;
Two &operator=(Two &&) noexcept = default;
std::vector<One> ones;
};
代码得到如下错误代码g++ -std=c++14 example.cpp
In file included from /usr/include/c++/7.3.1/memory:64:0,
from example.cpp:1:
/usr/include/c++/7.3.1/bits/stl_construct.h: In instantiation of 'void std::_Construct(_T1*, _Args&& ...) [with _T1 = One; _Args = {const One&}]':
/usr/include/c++/7.3.1/bits/stl_uninitialized.h:210:18: required from 'static _ForwardIterator std::__uninitialized_fill_n<_TrivialValueType>::__uninit_fill_n(_ForwardIterator, _Size, const _Tp&) [with _ForwardIterator = One*; _Size = long unsigned int; _Tp = One; bool _TrivialValueType = false]'
/usr/include/c++/7.3.1/bits/stl_uninitialized.h:255:17: required from '_ForwardIterator std::uninitialized_fill_n(_ForwardIterator, _Size, const _Tp&) [with _ForwardIterator = One*; _Size = long unsigned int; _Tp = One]'
/usr/include/c++/7.3.1/bits/stl_uninitialized.h:366:39: required from '_ForwardIterator std::__uninitialized_fill_n_a(_ForwardIterator, _Size, const _Tp&, std::allocator<_Tp2>&) [with _ForwardIterator = One*; _Size = long unsigned int; _Tp = One; _Tp2 = One]'
/usr/include/c++/7.3.1/bits/stl_vector.h:1337:33: required from 'void std::vector<_Tp, _Alloc>::_M_fill_initialize(std::vector<_Tp, _Alloc>::size_type, const value_type&) [with _Tp = One; _Alloc = std::allocator<One>; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::value_type = One]'
/usr/include/c++/7.3.1/bits/stl_vector.h:298:27: required from 'std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>::size_type, const value_type&, const allocator_type&) [with _Tp = One; _Alloc = std::allocator<One>; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::value_type = One; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<One>]'
example.cpp:40:39: required from here
/usr/include/c++/7.3.1/bits/stl_construct.h:75:7: error: use of deleted function 'One::One(const One&)'
{ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
example.cpp:29:3: note: declared here
One(const One &) = delete;
^~~
我已经尽力强制它使用移动构造函数。我还尝试使用 std::move 创建自己的移动构造函数,但这导致了相同的编译错误。我知道 std::vector 测试 move_if_noexcept(),但无法找出原因。我做错了什么?
因为问题出在这里:
Two(std::size_t numof_ones, std::size_t num_of_datas)
: ones(numof_ones, One(num_of_datas))
{ }
你不能从你在这里创建的 One
移动,你真的需要从它复制 numof_ones
次。
不幸的是,如果 One
没有默认构造函数或复制构造函数,就没有简单的方法来构造大小为 numof_ones
的 std::vector<One>
。您选择的构造函数将您赋予它的单个值 numof_ones
份 复制到向量的每个元素中。
最简单的解决方案可能是不在构造函数初始化列表中初始化 ones
,而是在构造函数的主体中初始化它:
Two(std::size_t numof_ones, std::size_t num_of_datas) {
ones.reserve(numof_ones);
for (size_t i = 0; i != numof_ones; ++i) {
ones.emplace_back(num_of_datas);
}
}
(从技术上讲,您可能会使用带有两个迭代器并提供您自己的自定义迭代器的 std::vector
构造函数,但这可能不值得付出努力)。