C++ 移入容器
C++ moving into a container
假设我有一个容器,为了论证我们假设一个向量:
std::vector<T> v;
并假设我的类型 'T' 有一个 move ctor:
T(T&& move_from) noexcept //...implementation
但是我没有移动赋值运算符。
是否可以移动一个值来键入 T 到向量中某个索引处的位置?类似于我可以在两个元素之间或最后通过使用以下方式移动它来插入元素的方式:
v.emplace(std::move(value));
v.emplace_back(std::move(value));
...每个人似乎都建议替换矢量元素的一种方法是使用:
v.at(index) = value;
然而什么是绑定调用复制构造函数(或者无论如何 opearator= copy 被规范地调用)。
我想到了在所需索引处的元素上使用 std::swap
和我希望移入的值,但是,这似乎有点浪费,因为我不需要我的值不再替换并且如果我没有在我的 class 上定义 swap()
则 std::swap 似乎只是调用两个元素的复制构造器......这只会使整个事情成为两倍贵。
通常应该如何在向量和 stl 容器中的索引处移动元素(如果可以推广的话)?有没有理由为什么一开始就不应该这样做?
注意,我问的是如何在仅定义了标准移动构造函数的类型上执行此操作,如果我在类型上定义 swap() ,我可以看到它变得相当容易。但是,swap 方法的存在似乎并不常见,所以我宁愿避免这种情况......更不用说当该方法不可用时,我不得不用 sfinae 来解决这个问题(这将使代码不可读)或遭受对复制 ctor 的两次调用的惩罚。
v.at(index) = std::move(value)
取决于是否存在移动赋值运算符。 std::swap
解决方案需要一个 nothrow 移动赋值运算符。
此外,定义 T::swap
绝对没有什么不好,它可能比回退到 std::swap
.
稍微更有效率
为 T
编写移动赋值运算符将是一个很好的解决方案。如果你不能那样做,那么可以就地创建和销毁,例如:
T *ptr = &v.at(index);
ptr->~T();
new(ptr) T( std::move(value) );
这依赖于 T
的移动构造函数是 noexcept,否则如果它抛出你就被塞满了。
使用 swap
或移动赋值的一个很好的理由是它本质上是异常安全的。移动赋值运算符也将对其他容器操作有益。
假设我有一个容器,为了论证我们假设一个向量:
std::vector<T> v;
并假设我的类型 'T' 有一个 move ctor:
T(T&& move_from) noexcept //...implementation
但是我没有移动赋值运算符。
是否可以移动一个值来键入 T 到向量中某个索引处的位置?类似于我可以在两个元素之间或最后通过使用以下方式移动它来插入元素的方式:
v.emplace(std::move(value));
v.emplace_back(std::move(value));
...每个人似乎都建议替换矢量元素的一种方法是使用:
v.at(index) = value;
然而什么是绑定调用复制构造函数(或者无论如何 opearator= copy 被规范地调用)。
我想到了在所需索引处的元素上使用 std::swap
和我希望移入的值,但是,这似乎有点浪费,因为我不需要我的值不再替换并且如果我没有在我的 class 上定义 swap()
则 std::swap 似乎只是调用两个元素的复制构造器......这只会使整个事情成为两倍贵。
通常应该如何在向量和 stl 容器中的索引处移动元素(如果可以推广的话)?有没有理由为什么一开始就不应该这样做?
注意,我问的是如何在仅定义了标准移动构造函数的类型上执行此操作,如果我在类型上定义 swap() ,我可以看到它变得相当容易。但是,swap 方法的存在似乎并不常见,所以我宁愿避免这种情况......更不用说当该方法不可用时,我不得不用 sfinae 来解决这个问题(这将使代码不可读)或遭受对复制 ctor 的两次调用的惩罚。
v.at(index) = std::move(value)
取决于是否存在移动赋值运算符。 std::swap
解决方案需要一个 nothrow 移动赋值运算符。
此外,定义 T::swap
绝对没有什么不好,它可能比回退到 std::swap
.
为 T
编写移动赋值运算符将是一个很好的解决方案。如果你不能那样做,那么可以就地创建和销毁,例如:
T *ptr = &v.at(index);
ptr->~T();
new(ptr) T( std::move(value) );
这依赖于 T
的移动构造函数是 noexcept,否则如果它抛出你就被塞满了。
使用 swap
或移动赋值的一个很好的理由是它本质上是异常安全的。移动赋值运算符也将对其他容器操作有益。