在不触发默认构造函数且仅使用移动语义的情况下将向量从 N1 缩小到 N2 项

Shrink a vector from N1 down to N2 items without triggering the default constructor and using only move semantics

你能帮我用一种有效的方法将 std::vector<T>N1 缩小到 N2 (N2 <= N1) 个项目而不需要 T 有一个默认构造函数(即 resize() 不是一个选项,因为它需要一个默认构造函数,因为它也可以用来增长),并且只使用移动语义(不需要复制 constructor/assignment 运算符T)?该操作是否实际缩小分配的内存是可选的(我还没有决定哪个更适合我的程序)。

到目前为止我尝试过的:

template<typename T> void Filter(vector<T> &v) {
    // ... Filter the N1 items of the vector and move them to the first N2 positions
    vector<T>(move(v)).swap(v); // this is wrong
}

这样的事情怎么样?

void foo(std::vector<T>& vec)
{
    const std::size_t n = /* ... */;
    std::vector<T>(
        std::make_move_iterator(std::begin(vec)),
        std::make_move_iterator(std::begin(vec) + n).swap(vec);
}

最简单的解决方案是擦除元素:

v.erase(v.begin() + N2, v.end());

如果需要,您可以减小保留大小:

v.shrink_to_fit();

您还可以使用 std::move 的其他重载来创建包含元素子集的新向量:

std::vector<T> filtered;
filtered.reserve(N2);
std::move(v.begin(), v.begin() + N2, 
          std::back_insert_iterator(filtered));
return filtered;

如果您需要就地完成,也许 erase 就足够了:

v.erase(v.begin() + N2, v.end());

erase 似乎更干净:

v.erase(v.begin() + N2, v.end());

但是 resize 的选项是提供一个虚拟对象:

auto& dummy = v[0]; // assuming non-empty, else create a new dummy object
v.resize(N2, dummy);