为什么我不能自己移动构造一个unique_ptr?

时间:2018-10-24 02:49:14

标签: c++ c++11 unique-ptr clang++ std-function

我最近正在使用一些代码,这些代码使用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=junique_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);
}

1 个答案:

答案 0 :(得分:2)

不需要标准库类来检查右值的自赋值。根据[res.on.arguments] /(1.3),

  

如果函数参数绑定到右值引用参数,则实现可以假定   此参数是对此参数的唯一引用。

因此,当您尝试执行自我移动分配时,会发生未定义的行为。