首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

调用`std::unique_ptr` move构造函数时“使用已删除的函数”?

问题分析

当你在调用 std::unique_ptr 的 move 构造函数时遇到“使用已删除的函数”错误,通常是因为以下几个原因之一:

  1. 自定义删除器:如果你为 std::unique_ptr 提供了自定义删除器,而这个删除器没有正确实现移动语义。
  2. 不可移动类型std::unique_ptr 所指向的对象类型本身是不可移动的。
  3. 移动构造函数被删除std::unique_ptr 所指向的对象类型的移动构造函数被显式删除。

原因及解决方法

1. 自定义删除器

如果你使用了自定义删除器,确保删除器也支持移动语义。例如:

代码语言:txt
复制
#include <iostream>
#include <memory>

struct CustomDeleter {
    void operator()(int* ptr) const {
        std::cout << "Deleting pointer" << std::endl;
        delete ptr;
    }

    // 确保删除器支持移动语义
    CustomDeleter(CustomDeleter&&) = default;
    CustomDeleter& operator=(CustomDeleter&&) = default;
};

int main() {
    std::unique_ptr<int, CustomDeleter> ptr1(new int(42));
    std::unique_ptr<int, CustomDeleter> ptr2(std::move(ptr1));
    return 0;
}

2. 不可移动类型

确保 std::unique_ptr 所指向的对象类型是可移动的。例如:

代码语言:txt
复制
#include <iostream>
#include <memory>

struct NonMovable {
    NonMovable() = default;
    ~NonMovable() = default;

    // 禁止移动构造函数和移动赋值操作符
    NonMovable(NonMovable&&) = delete;
    NonMovable& operator=(NonMovable&&) = delete;
};

int main() {
    // 这将导致编译错误,因为 NonMovable 是不可移动的
    std::unique_ptr<NonMovable> ptr1(new NonMovable);
    std::unique_ptr<NonMovable> ptr2(std::move(ptr1));
    return 0;
}

3. 移动构造函数被删除

确保 std::unique_ptr 所指向的对象类型的移动构造函数没有被显式删除。例如:

代码语言:txt
复制
#include <iostream>
#include <memory>

struct Movable {
    Movable() = default;
    ~Movable() = default;

    // 确保移动构造函数没有被删除
    Movable(Movable&&) = default;
    Movable& operator=(Movable&&) = default;
};

int main() {
    std::unique_ptr<Movable> ptr1(new Movable);
    std::unique_ptr<Movable> ptr2(std::move(ptr1));
    return 0;
}

总结

  • 自定义删除器:确保删除器支持移动语义。
  • 不可移动类型:确保 std::unique_ptr 所指向的对象类型是可移动的。
  • 移动构造函数被删除:确保 std::unique_ptr 所指向的对象类型的移动构造函数没有被显式删除。

通过以上方法,你应该能够解决调用 std::unique_ptr move 构造函数时“使用已删除的函数”的问题。

参考链接

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

JEP 447 发布,可在构造函数 super()调用之前执行语句

该 JEP 来自 Project Amber 项目,提议允许在构造函数 super() 调用之前出现不引用正在创建实例语句,并保留构造函数现有的安全性和初始化保证。...传统上,要求 Java 构造函数将对另一个构造函数显式调用作为第一条语句。这个约束确保了自上而下执行顺序,并防止对未初始化字段访问,极大地限制了构造函数逻辑表达性和可读性。...JEP 447 放宽了这些限制,允许在显式构造函数调用之前出现不引用正在创建实例语句。...以前,由于超类构造函数调用必须作为第一条语句,这就需要使用辅助方法。...这个更新不需要对 Java 虚拟机(JVM)做任何修改,仅依赖 JVM 现有的能力来验证和执行构造函数调用之前代码。

18410
  • 现代C++之手写智能指针

    把赋值函数参数类型 unique_ptr& 改成了 unique_ptr,在构造参数直接生成新智能指针,从而不再需要在函数体中构造临时对象。..._2{std::move(ptr1)}; // 调用是默认移动构造,而不是带模板移动构造 bitwise move if (ptr2_2.get() !...,而不是带参数移动构造,再调用移动赋值 unique_ptr ptr4(std::move(new circle)); // ok 调用带模板移动构造 } 调用与结果如上代码所示...但是,一个对象只能被单个 unique_ptr所拥有,这显然不能满足所有使用场合需求。一种常见情况是,多个智能指针同时拥有一个对象;当它们全部都失效,这个对象也同时会被删除。...针对第一点:例如:ptr2 = std::move(ptr1); 会先调用赋值函数,由编译器决定调用是拷贝构造还是移动构造,造出一个新临时对象出来,临时对象会在跳出作用域后被析构掉。

    2.9K10

    智能指针探究

    需要注意是,使用 std::move 函数并不会移动对象或释放资源。它只是将左值转换为右值引用,以便可以使用移动构造函数或移动赋值运算符来转移对象所有权。...当你使用std::move函数将一个unique_ptr对象转化为右值引用并将其传递给另一个unique_ptr对象来初始化时,就会调用这个构造函数 unique_ptr& operator=(unique_ptr...当你使用std::move函数将一个unique_ptr对象转化为右值引用并将其赋值给另一个unique_ptr对象来初始化时,就会调用这个运算符 第三行代码创建一个unique_ptr对象p1...,并且使用new int动态分配内存来存储一个int类型对象 第四行代码创建另一个unique_ptr对象p2,并且使用std::move()将p1转化为右值引用并传递给p2移动构造函数,...当使用new操作符创建一个新对象,会为该对象分配内存,并调用构造函数来初始化它。当不再需要这个对象,应该使用delete操作符来删除它。

    8610

    掌握C++中智能指针综合指南:深入现代内存管理

    不要delete p.get()返回值 ,会导致对一块内存delete两次错误。2.3.3、指定删除器如果用shared_ptr管理非new对象或是没有析构函数,应当为其传递合适删除器。...0,自动调用删除器DeleteIntPtr来释放对象内存。...delete p;});当使用shared_ptr管理动态数组,需要指定删除器,因为shared_ptr默认删除器不支持数据对象,代码如下:std::shared_ptr p3(new int...不允许复制,但可以通过函数返回给其他unique_ptr,还可以通过std::move来转移到其他unique_ptr,这样它本身就不再拥有原来指针所有权了。...需要注意是,获取自身智能指针函数仅在shared_ptr构造函数调用之后才能使用,因为enable_shared_from_this内部weak_ptr只有通过shared_ptr才能构造

    11200

    【Advanced C++】: 详解RAII,教你如何写出内存安全代码

    其异常安全保障就是析构函数一定会在对象归属scope退出自动被调用(在本例中在函数返回前执行)。...在上述代码中,当main函数退出std::unique_ptr在自己析构函数中释放指针,而为了防止有别的 std::unique_ptr指向自己管理对象而导致提早释放与空指针访问, std:...这是因为 std::unique_ptr实现了 move constructor(一种可以将资源从另一个对象“偷”过来构造函数)并在返回将指针传给了main函数中 obj变量。...不过,细心同学可能发现了,全程 unique_ptr move constructor都没有被call过,但是我之前明确说了,main函数 obj是用 get_object函数构造 unique_ptr...此时我们可以清晰地看到,main函数 obj是通过 move constructor构造,并且在其构造完成之后, get_object函数构造 unique_ptr对象被析构了,因为我们已经提早将其内部指针替换成了

    3.2K30

    性能大杀器:c++中copy elision

    ,此处假设为temp2 Copy ctor // 通过调用拷贝构造函数,将temp2值赋值给o2 在上一节中,我们提到过,可以通过使用移动构造方式来避免拷贝,为了测试该功能,尝试在Obj类中新增一个移动构造函数...,不禁奇怪,为什么在CreateObj2()函数中,创建temp明明是一个左值,此处却调用是移动构造即当做右值使用呢?...volatile命名对象,其类型与函数返回类型相同时,编译器可以优化掉拷贝或移动操作,直接将自动对象构造函数调用返回对象中。...这意味着,当函数返回一个自动对象,编译器可以优化掉不必要拷贝或移动操作,直接将自动对象构造函数调用返回对象中,以提高效率。这种优化在 C++ 标准中被明确规定,以支持更高效代码生成。...标准这一规定,使得原本不支持拷贝对象,作为函数返回值,也成了可能。

    14910

    探究C++11智能指针之std::unique_ptr

    std::unique_ptr禁止复制语义 和 std::shared_ptr区别:unique_ptr是移动构造unique_ptr不可拷贝和赋值,但可以被移动,unique_ptr禁止复制语义,拷贝构造函数和复制运算符...当unique_ptr被销毁,它所指向对象也被销毁。...(num); return 0; } std::unique_ptrstd::move不解之缘 std::unique_ptr无法被复制,但可以使用移动构造std::unique_ptr对象持有的堆内存转移给另外一个对象...那么,是不是所有的对象,都可以用std::move操作呢?答案是否定,只有实现了移动构造函数或移动运算符类才可以。恰恰std::unique_ptr实现了二者。...指针创建成功,其析构函数都会被调用,确保动态资源被释放。

    2.3K10

    彻底搞懂之C++智能指针

    因此,当需要纯 C++ 对象智能指针,请使用make_unique帮助程序函数。 下图演示了两个 unique_ptr 实例之间所有权转换。...将实例添加到 unique_ptr C++ 标准库容器是有效,因为移动构造函数 unique_ptr 无需复制操作。...但是可以进行移动构造和移动赋值操作 3、保存指向某个对象指针,当它本身被删除释放时候,会使用给定删除器释放它指向对象 用法: std::unique_ptrp1(new int(5))...但是,你可以使用 weak_ptr 来尝试获取用于初始化新副本 shared_ptr 。 如果删除内存,则 bool 运算符将 weak_ptr 返回 false 。...如果函数使用new分配内存,并返还指向该内存指针,将其返回类型声明为unique_ptr是不错选择。这样,所有权转让给接受返回值unique_ptr,而该智能指针将负责调用delete。

    3.6K10

    女朋友:一个 bug 查了两天,再解决不了,和你代码过去吧!

    , this);     //代码省略... }; 这样写,是没法通过编译,因为 std::unique_ptr 拷贝构造函数定义如下: class unique_ptr ...,所以无法在 HttpSession 初始化列表中调用其拷贝构造函数赋值给 m_spConnection 对象,好在 std::unique_ptr 移动构造函数Move Constructor)... 构造函数中又变成左值了,所以我们需要再次 std::move 一下,修改后代码如下: class HttpSession { public:     HttpSession(std::unique_ptr...HttpSession 构造函数使用 pConnection 调用 getIP 和 getPort 方法了,应该改用 m_spConnection 来调用这两个方法,修改后代码如下: class HttpSession...,尤其是在和左值、右值、移动构造std::movestd::forward 等特性结合使用时,需要多加小心。

    68420

    Modern C++ 最核心变化是什么?

    C++ 通过拷贝构造函数和拷贝赋值操作符为类设计了拷贝/复制概念,但为了实现对资源移动操作,调用者必须使用先复制、再析构方式。否则,就需要自己实现移动资源接口。...name 构造a调用了一次字符串构造函数和一次字符串移动构造函数。...如果使用 const string& name 接收参数,那么会有一次构造函数和一次拷贝构造,以及一次 non-trivial 析构。...} 如果函数按值返回,return 语句又直接返回了一个栈上左值对象(输入参数除外),标准要求优先调用移动构造函数,如果不符再调用拷贝构造函数。...5.std::vector 增长 又一个隐蔽优化。当 vector 存储容量需要增长,通常会重新申请一块内存,并把原来内容一个个复制过去并删除。对,复制并删除,改用移动就够了。

    99321

    【C++11】 使用C++11解决内存泄露--智能指针

    在实际编程,有三种智能指针可供使用,分别是:std::shared_ptr、std::unique_ptrstd::weak_ptr。...运行结果如下: a and p point to the same location 10 10 10 1.3 指定指针删除器 智能指针在初始化时可以指定删除器,在指针计数为零,自动调用指定删除器从而释放指针指向内存存...,因为调用顺序不同可能引起内存泄露,因此在使用时应当先创建对象,在传入函数使用。...如果函数要返回this指针,不要将this当做智能共享指针进行返回。因为如果使用同一个指针(this)构造了两个对象,析构可能导致重复析构。...如果想要将一个独占指针分配给另外一个独占指针,有两种方法,分别是: 通过函数返回值; 通过std::move方法转义指针对象所有权.

    70310

    llvm入门教程-Kaleidoscope前端-2-解析器和AST

    (Result); } 此例程非常简单:它预期在当前令牌为tok_number令牌调用。...调用函数,该函数期望当前令牌是一个‘(’令牌,但在解析子表达式之后,可能没有‘)’在等待。例如,如果用户键入“(4x”而不是“(4)”),解析器应该会发出错误。...2)此函数另一个有趣之处在于,它通过调用ParseExpression使用递归(我们很快就会看到ParseExpression可以调用ParseParenExpr)。...其中一个有趣方面是,它使用前瞻(look ahead)来确定当前标识符是独立变量引用还是函数调用表达式。...这使用前瞻来确定正在检查哪种类型表达式,然后使用函数调用对其进行解析。 现在已经处理了基本表达式,我们需要处理二元表达式。它们稍微复杂一些。

    1.8K30

    【Example】C++ 标准库智能指针 unique_ptr 与 shared_ptr

    该对象在其构造函数中创建或接收新分配资源,并在其析构函数中将此资源删除。 RAII 原则可确保当所属对象超出范围,所有资源都能正确返回到操作系统。...unique_ptr 没有拷贝构造函数,因此不能用于赋值。该指针最常用情况是单例模式和编译防火墙封装。...unique_ptr um_barin = std::move(u_brain); um_barin->HelloWorld(); // 移动方法2 std::swap(u_brain...因此 shared_ptr 是最常用智能指针,也是最容易出问题智能指针。 使用应当注意: 1,不要将存在裸指针交由 shared_ptr,任何形式智能指针都不应该去托管已有的裸指针。...使用make_shared语句更简单,因为只涉及到一个函数调用。 这样会更有效,因为库可能会对对象和智能指针进行一个分配。

    1.1K20

    基础知识_Cpp

    放弃 (核心已转储) using namespace std 1.在头文件中一定不要使用,否则在别人引用你头文件后,如果std函数名和其他库中冲突了,可能会带来麻烦。...将拷贝构造函数和拷贝赋值运算符设置为私有,这样继承nocopyable类给对象赋值或拷贝构造,会先调用父类nocopyable函数,但是这两个函数是私有的,所以会引发编译错误。...一般构造函数都是公有地,创建一个对象就会自动调用构造函数。...拷贝构造函数调用时机 用一个类对象去初始化另一个对象。 往函数中传递对象参数。 从函数中返回一个对象。...当A a= new A();创建新对象,是使用new operator。会做两件事,一是调用operator分配内存,二是调用对象构造函数

    2K30

    智能指针详解

    智能指针特点包括: 拥有权管理:智能指针拥有其所指向对象,负责在适当时机释放内存。这意味着当智能指针超出作用域或不再需要,它会自动调用析构函数来释放内存。...异常安全性:智能指针在异常情况下能够保证资源正确释放。即使发生异常,智能指针也会在其作用域结束被销毁,并调用析构函数来释放资源。...std::unique_ptr支持所有权转移,可以通过move将一个std::unique_ptr实例所有权转移到另一个实例。这种所有权转移可以通过移动构造函数和移动赋值运算符来实现。...// 创建一个 std::unique_ptr unique_ptr uResource1 = make_unique(); // 使用移动构造函数将所有权转移到另一个...每当新shared_ptr添加、超出范围或重置增加和减少引用计数,当引用计数达到零,控制块将删除内存资源和自身。

    30340

    C++智能指针

    原理: 将我们分配动态内存都交给有生命周期对象来处理,当对象过期,让它析构函数删除指向内存。...无法进行左值unique_ptr复制构造,也无法进行左值复制赋值操作,但允许临时右值赋值构造和赋值。std::move。把右值转换为左值。...,同时指向类型为T对象,接受一个D类型删除器d,使用删除器d来释放内存 删除器 利用一个仿函数实现一个删除器 class DestructTest { public: void operator...(可以对比理解一下类中深浅拷贝) unique_ptr s1(new int(1)); unique_ptr s2(new int(2)); s1 = std::move(s2)...---- 在必要时候可以转换成shared_ptr .lock(); 完美解决。 类中弱指针,用shared指针构造weak指针,用时候,将weak指针转成shared指针来调用成员函数

    44620
    领券