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

含Eigen::CholmodDecomposition的自定义类拷贝触发‘Use of deleted function’错误

为什么包含Eigen::CholmodDecomposition的类无法拷贝?如何解决?

你遇到的报错本质是Eigen的CholmodDecomposition类型是不可拷贝的,这直接导致你的TestClass默认拷贝构造函数被编译器自动删除了——因为它包含了一个不支持拷贝的成员变量。

问题根源与违反的规则

  1. C++默认拷贝构造函数的生成规则:当类中的任何成员变量的拷贝构造函数被删除(或者不可访问)时,编译器会自动删除该类的默认拷贝构造函数。这是C++的安全机制,避免生成可能导致资源错误的拷贝逻辑。
  2. CholmodDecomposition不可拷贝的原因:这个类底层封装了Cholmod库的底层资源(比如分配的内存、分解后的计算状态、库的句柄等),这些资源不适合通过浅拷贝复制——比如两个对象共享同一块内存,销毁时会重复释放导致崩溃。因此Eigen刻意禁用了它的拷贝构造函数和赋值运算符。

在你的代码中,TestClass test2 = test;这一行尝试调用TestClass的拷贝构造函数,但因为成员solver(CholmodDecomposition类型)的拷贝构造已经被删除,编译器无法生成合法的默认拷贝构造,所以抛出了错误。

解决方法

根据你的业务需求,这里有几个可行的方案:

1. 显式禁用拷贝操作(推荐,如果你不需要拷贝对象)

如果你的逻辑里不需要复制TestClass对象,直接显式删除拷贝构造和赋值运算符,从根源避免意外触发:

#include <RcppEigen.h>
using namespace std;

class TestClass{
public:
    Eigen::CholmodDecomposition<Eigen::SparseMatrix<double> > solver;
    Eigen::MatrixXd solve(const Eigen::SparseMatrix<double>&, const Eigen::MatrixXd&);
    TestClass(){};
    
    // 显式删除拷贝构造和赋值运算符
    TestClass(const TestClass&) = delete;
    TestClass& operator=(const TestClass&) = delete;
};

Eigen::MatrixXd TestClass::solve(const Eigen::SparseMatrix<double>& A, const Eigen::MatrixXd& b){
    solver.compute(A);
    return solver.solve(b);
}

//[[Rcpp::export]]
Eigen::MatrixXd cholmodsolver(const Eigen::SparseMatrix<double>& A, const Eigen::MatrixXd& b){
    TestClass test;
    // 现在如果尝试拷贝会直接报错,避免后续问题
    return test.solve(A, b);
}

2. 使用智能指针管理求解器(如果需要移动/拷贝语义)

如果你确实需要转移或复制TestClass对象,可以用智能指针封装solver,避免直接持有不可拷贝的对象:

方案2.1:用std::unique_ptr支持移动语义

如果只需要转移对象所有权而非拷贝,unique_ptr是最优选择——它禁止拷贝,但允许移动:

#include <RcppEigen.h>
#include <memory>
using namespace std;

class TestClass{
public:
    std::unique_ptr<Eigen::CholmodDecomposition<Eigen::SparseMatrix<double> > > solver;
    Eigen::MatrixXd solve(const Eigen::SparseMatrix<double>&, const Eigen::MatrixXd&);
    
    TestClass() : solver(std::make_unique<Eigen::CholmodDecomposition<Eigen::SparseMatrix<double> > >()){};
    
    // 允许移动构造和赋值
    TestClass(TestClass&&) = default;
    TestClass& operator=(TestClass&&) = default;
    
    // 禁止拷贝
    TestClass(const TestClass&) = delete;
    TestClass& operator=(const TestClass&) = delete;
};

Eigen::MatrixXd TestClass::solve(const Eigen::SparseMatrix<double>& A, const Eigen::MatrixXd& b){
    solver->compute(A);
    return solver->solve(b);
}

//[[Rcpp::export]]
Eigen::MatrixXd cholmodsolver(const Eigen::SparseMatrix<double>& A, const Eigen::MatrixXd& b){
    TestClass test;
    // 使用std::move转移所有权
    TestClass test2 = std::move(test);
    return test2.solve(A, b);
}

方案2.2:用std::shared_ptr支持共享拷贝

如果多个TestClass对象可以共享同一个求解器实例(比如复用已完成的分解结果),可以用shared_ptr——它支持拷贝,多个对象共享底层的solver:

#include <RcppEigen.h>
#include <memory>
using namespace std;

class TestClass{
public:
    std::shared_ptr<Eigen::CholmodDecomposition<Eigen::SparseMatrix<double> > > solver;
    Eigen::MatrixXd solve(const Eigen::SparseMatrix<double>&, const Eigen::MatrixXd&);
    
    TestClass() : solver(std::make_shared<Eigen::CholmodDecomposition<Eigen::SparseMatrix<double> > >()){};
    
    // 默认拷贝构造和赋值即可,shared_ptr会自动管理引用计数
};

Eigen::MatrixXd TestClass::solve(const Eigen::SparseMatrix<double>& A, const Eigen::MatrixXd& b){
    solver->compute(A);
    return solver->solve(b);
}

//[[Rcpp::export]]
Eigen::MatrixXd cholmodsolver(const Eigen::SparseMatrix<double>& A, const Eigen::MatrixXd& b){
    TestClass test;
    TestClass test2 = test; // 现在可以正常编译,test和test2共享同一个solver
    return test2.solve(A, b);
}

3. 手动实现拷贝构造(不推荐)

理论上你可以手动实现TestClass的拷贝构造,但CholmodDecomposition没有公开的状态拷贝接口——你只能重新调用compute来复制分解结果,这不仅低效,还需要额外存储原始矩阵A,容易引入bug,因此不推荐这种方案。

内容的提问来源于stack exchange,提问作者mkln

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:11:17