简体   繁体   中英

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

Could you help me with an efficient way to shrink an std::vector<T> from N1 down to N2 ( N2 <= N1 ) items in it without requiring T to have a default constructor (ie resize() is not an option because it requires a default constructor because it can be used to grow also), and using only move semantics (without requiring a copy constructor/assignment operator in T )? Whether the operation actually shrinks the allocated memory is optional (I haven't yet decided which one is better for my program).

What I have tried so far:

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
}

What about something like this?

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);
}

Simplest solution is to erase the elements:

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

You can reduce the reserved size if desired:

v.shrink_to_fit();

You can also use the other overload of std::move to create a new vector containing the subset of elements:

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

If you need to do it in-place, maybe just erase will be enough:

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

erase seems the cleaner:

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

but option with resize is to provide a dummy object:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM