This question already has an answer here:
I was recently working with some code that uses a std::vector
of std::unique_ptr<T>
with a custom deleter of type std::function<void(T*)>
. The code is attempting to remove values that meet a certain condition from the vector:
size_t j = 0;
for (size_t i = 0; i < vec.size(); i++) {
if (!condition(vec[i].get()) {
vec[j] = std::move(out[i]);
j++;
}
}
vec.resize(j);
In troubleshooting a bad_function_call
thrown from the destructor of vec
, I found that when i=j
and a unique_ptr
is move-constructed with itself, it loses its custom deleter. In other words, vec[j]
will still point to the correct value, but its deleter will be a default-constructed std::function
.
Why does this happen? What rule does this code break?
FWIW, I can only make it happen with clang, and only on certain platforms. Adding a guard for i=j
fixes the problem.
MCVE:
#include <memory>
#include <vector>
#include <functional>
using int_ptr= std::unique_ptr<int, std::function<void(int*)>>;
int_ptr make_int_ptr(int val) {
auto deleter = [](int* q) { delete q; };
int* v = new int;
*v = val;
return int_ptr{v, deleter};
}
int main() {
auto a = make_int_ptr(4);
a = std::move(a);
}
Aucun commentaire:
Enregistrer un commentaire