【问题标题】:Why can't I move-construct a unique_ptr with itself? [duplicate]为什么我不能自己移动构造一个 unique_ptr ? [复制]
【发布时间】:2019-03-28 08:41:24
【问题描述】:

我最近正在处理一些使用std::unique_ptr<T>std::vectorstd::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);

在对vec 的析构函数抛出的bad_function_call 进行故障排除时,我发现当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);
}

【问题讨论】:

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


【解决方案1】:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-06-05
    • 2017-09-20
    • 2014-01-24
    • 1970-01-01
    相关资源
    最近更新 更多