我最近正在使用一些代码,这些代码使用std::vector
中的std::unique_ptr<T>
和类型为std::function<void(T*)>
的自定义删除器。该代码正在尝试从向量中删除满足特定条件的值:
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);
在对从bad_function_call
的析构函数中抛出的vec
进行故障排除时,我发现当i=j
和unique_ptr
自身移动构造时,它会丢失其自定义删除器。换句话说,vec[j]
仍将指向正确的值,但其删除器将是默认构造的std::function
。
为什么会这样?该代码违反什么规则?
FWIW,我只能使用clang来实现,并且只能在某些平台上实现。为i=j
添加防护措施可以解决此问题。
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);
}
答案 0 :(得分:2)
不需要标准库类来检查右值的自赋值。根据[res.on.arguments] /(1.3),
如果函数参数绑定到右值引用参数,则实现可以假定 此参数是对此参数的唯一引用。
因此,当您尝试执行自我移动分配时,会发生未定义的行为。