C++加法运算符多次重载

C++ addition operator overloading multiple times

我正在尝试使一些数学结构起作用,其中包含 'Cells',它表示具有一组输入和输出的数学函数。

每个数学运算都有自己的 class,它继承自 Cell。使用一些运算符重载,我想在两个单元格上调用 operator+ 时生成一个新的 Add-Cell。

到目前为止一切正常,但我遇到了问题。

我写了一个小的演示代码来说明我的问题:

想象一下这个 class 完全实现 copy/move assignment/construction 以及自定义析构函数和构造函数。


class Cell{

private:
    Cell* A = nullptr;
    Cell* B = nullptr;
public:
    Cell() {
        std::cout << "default constructed" << std::endl;
    }
    Cell(Cell& A, Cell& B) {
        this->A = &A;
        this->B = &B;
        std::cout << "default constructed" << std::endl;
    }
    T(const Cell& other){
        this->A = other.A;
        this->B = other.B;
        std::cout << "copy constructed" << std::endl;

    }
    T(Cell&& other){
        this->A = other.A;
        this->B = other.B;
        std::cout << "move constructed" << std::endl;

    }
    Cell& operator=(Cell&& other){
        this->A = other.A;
        this->B = other.B;
        std::cout << "move assigned" << std::endl;
        return *this;

    }
    Cell& operator=(const Cell&& other){
        this->A = other.A;
        this->B = other.B;
        std::cout << "copy assigned" << std::endl;
        return *this;
    }

    Cell operator+(Cell& other){
        return T{*this, other};
    }

    virtual ~Cell() {
        std::cout << "destructed" << std::endl;
    }

};

和我的代码差不多。这里 Cell 可以被认为是具有 2 个先前数学运算的任何类型的单元格。

所以当我尝试做这样的事情时,问题就出现了:

    Cell t1{};
    Cell t2{};
    Cell t3{};

    auto h = t1 + t2 + t3;

它创建了 3 个空的 Cell 对象。然后它基于 t1t2 创建一个新的 Cell 并使用它来创建一个新的 Cellt3。这里的问题是第一个 Cell = t1 + t2 将在该操作后直接被破坏,最后的树将持有无效引用。

这个问题可以通过这样做很容易地解决:

    auto h1 = t1 + t2;
    auto h  = h1 + t3;

或在重载加法运算符 operator+.

中使用 new

我不想在操作员内部使用 new,因为清理它们最终只能通过使用某种跟踪系统来实现。

我想知道是否有解决这个问题的好方法。

我很高兴得到任何建议或帮助。

我们有 2021 年,所以使用 C++14 中的 C++11 std::unique_ptrstd::make_unique

class Cell{

private:
    using ptr = std::unique_ptr<Cell>;
    ptr A;
    ptr B;

public:
    Cell() {
        std::cout << "default constructed" << std::endl;
    }

    Cell(Cell&& A, Cell&& B) {
        this->A = std::make_unique<Cell>(std::move(A));
        this->B = std::make_unique<Cell>(std::move(B));
        std::cout << "default constructed" << std::endl;
    }

    T(Cell&& other){
        this->A = std::move(other.A);
        this->B = std::move(other.B);
        std::cout << "move constructed" << std::endl;

    }
    Cell& operator=(Cell&& other){
        this->A = std::move(other.A);
        this->B = std::move(other.B);
        std::cout << "move assigned" << std::endl;
        return *this;
    }

    Cell operator+(Cell&& other) && {
        return T{std::move(*this), std::move(other)};
    }

    ptr clone() const {
        if (this)
            return std::make_unique<Cell>(A->clone(), B->clone());
        return nullptr;
    }

    virtual ~Cell() {
        std::cout << "destructed" << std::endl;
    }
};

如果您需要实际的复制构造函数赋值,请使用 clone 方法。

或者您可以使用 shared_ptr,但在这种情况下 Cell 不可变会更安全。