You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Pybind11中封装显式禁用拷贝的C++类(支持移动语义)

在Pybind11中封装禁用拷贝、仅允许移动的C++类

如果你的C++类已经显式禁用了拷贝构造与拷贝赋值,同时默认了移动操作:

class Foo {
public:
    Foo(const Foo& other) = delete;
    Foo& operator=(const Foo& other) = delete;
    Foo(Foo&& other) = default;
    Foo& operator=(Foo&& other) = default; 
    // 其他成员逻辑...
};

要在Pybind11中严格遵循这个设计意图——强制使用移动操作、禁止拷贝,需要从两方面配置绑定逻辑:

1. 彻底禁用Python端的拷贝路径

Pybind11默认会尝试生成拷贝相关的绑定,我们需要主动拦截并禁用:

  • 用py::delete_function()标记拷贝构造函数为不可用
  • 实现__copy__和__deepcopy__方法抛出异常,阻止Python原生的复制操作

2. 绑定移动构造与移动赋值

显式绑定C++的默认移动构造和移动赋值运算符,让Python端可以正常使用移动语义。

完整绑定代码示例

#include <pybind11/pybind11.h>
#include "foo.h" // 你的Foo类头文件

namespace py = pybind11;

PYBIND11_MODULE(foo_module, m) {
    py::class_<Foo>(m, "Foo")
        // 禁用拷贝构造函数
        .def(py::init<const Foo&>(), py::delete_function())
        // 拦截Python的拷贝/深拷贝操作
        .def("__copy__", [](const Foo&) {
            throw std::runtime_error("Foo类禁止拷贝,请使用移动操作");
        })
        .def("__deepcopy__", [](const Foo&, py::dict) {
            throw std::runtime_error("Foo类禁止深拷贝,请使用移动操作");
        })
        // 绑定移动构造函数
        .def(py::init<Foo&&>())
        // 绑定移动赋值运算符
        .def("__assign__", [](Foo& self, Foo&& other) {
            self = std::move(other);
            return self;
        });

    // 若Foo有其他构造函数(比如默认构造),正常绑定即可
    // .def(py::init<>());
}

效果说明

  • Python端尝试拷贝Foo实例(比如a = Foo(); b = a或import copy; b = copy.copy(a))时,会直接抛出异常,严格遵循C++类的约束
  • 移动操作可正常使用,比如通过工厂函数返回右值实例,或在Python中通过b = Foo(std::move(a))(若你绑定了std::move接口)转移对象所有权

内容的提问来源于stack exchange,提问作者A. Fenzry

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 01:25:28