c ++覆盖已定义的变量

use*_*818 4 c++ pointers overwrite

我有以下主要功能,使用指针创建系数的乘积.它只是项目的一小部分,用于创建多项式:

#include "header.h"
int main()
{
    TermProd x = TermProd( new Coeff(4), new Coeff(8));
    x.print(); cout << endl;
    x = TermProd( new Coeff(8), new Coeff(15));
    x.print(); cout << endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

经过测试,覆盖似乎正在起作用.但是当我在x上调用print时,我会遇到分段错误.我已经尝试并盯着它看了一段时间,但我无法弄清楚真正的问题.此外,我的搜索没有导致正确的方向,所以我决定创建一个小的代码片段来重现错误.

我的header.h文件如下所示:

class Term{
public:
    Term(){};
    virtual ~Term(){};
        virtual Term* clone() const = 0;
    virtual void print() const = 0;
};

class Coeff:public Term{
    int m_val; //by def: >=0
public:
    // Constructor
    Coeff();
    Coeff(int val = 1):m_val(val)
    // Copy constructor
    Coeff* clone() const{return new Coeff(this->val());}
    // Destructor
    ~Coeff(){}
    // Accessors
    int val() const{return m_val;} ;
    // Print
    void print() const{cout << m_val; }
};

class TermProd:public Term{
    TermPtr m_lhs, m_rhs;
public:
    // Constructor
    TermProd(TermPtr lhs, TermPtr rhs):m_lhs(lhs), m_rhs(rhs){ }
    // Copy constructor
    TermProd* clone() const
    {
        return new TermProd(m_lhs->clone(), m_rhs->clone());
    }
    // Destructor
    ~TermProd(){ delete m_lhs;delete m_rhs;}
    // Accessors
    Term* lhs() const { return m_lhs; }
    Term* rhs() const { return m_rhs; } 
    // Print
    void print() const
    {
        cout << "("; m_lhs->print(); cout << '*'; m_rhs->print(); cout << ")";
    }       
 };
Run Code Online (Sandbox Code Playgroud)

Jar*_*Par 6

请注意,您不是要覆盖x变量,而是分配变量.这将调用operator=您的类型的默认值,这大致导致执行以下代码

  1. 构造函数TermProd::TermProd(TermPtr, TermPtr)被执行
  2. m_lhsm_rhs被复制到值x
  3. 现在运行步骤#1中创建的值的析构函数m_lhs并将m_rhs其删除

此时你有一个真正的问题.在步骤#2之后x,步骤#1中创建的值和临时值共享相同的值m_lhsm_rhs值.步骤#3中的析构函数删除它们但x仍然有对它们的引用,现在它们有效地指向死记忆

为了解决这个问题,你需要添加自己的operator=,正确处理赋值语义.例如

TermProd& operator=(const TermProd& other) {
  if (&other != this) {
    delete m_lhs;
    delete m_rhs;

    m_lhs = other.m_lhs->clone();
    m_rhs = other.m_rhs->clone();
  }
  return *this;
};
Run Code Online (Sandbox Code Playgroud)

为了使所有场景都正确,您还需要添加适当的复制构造函数

TermProd::TermProd(const TermProd& other) :
  m_lhs(other.m_lhs->clone()),
  m_rhs(other.m_rhs->clone())
{

}
Run Code Online (Sandbox Code Playgroud)

实际上,为了使这非常简单,你应该考虑使用它std::shared_ptr<Term>作为值TermPtr.它是一个指针,可以在没有上述所有开销的情况下进行共享