复制构造函数的问题

时间:2013-05-11 16:58:56

标签: c++ constructor copy

不要注意实际代码,只需阅读问题。 我有一个函数,它采用多项式类型的2个参数:

FiniteFieldElement(int l, Polynomial p, Polynomial irr)
{
    this->l = l;
    this->p = p;
    this->irr = irr;
}

我的理解是,当p和irr被传递时,将调用Polynomial的复制构造函数。

复制构造函数正常工作,因为我可以通过最后的断点进行验证。

Polynomial(const Polynomial& p)
{
    degree = p.degree;
    modulo = p.modulo;
    if (polynomial != p.polynomial)
    {
        polynomial = new int[degree + 1];
        for (int i = 0; i <= degree; i++)
        {
            polynomial[i] = p.polynomial[i];
        }
    }
}

但为什么我得到实际参数p和irr的错误(未初始化)值。复制构造函数的结果和实际参数之间可能会有什么结果?如果我将参数更改为参考参数,它可以正常工作。 (注意:多项式没有析构函数,如果有帮助的话)。

编辑:如果我使用复制构造函数Polynomial p1(p2)声明多项式,则p1会被正确初始化。在FiniteFieldElement类中,我得到了错误的多项式参数。我完全难过了。

3 个答案:

答案 0 :(得分:3)

  

我的理解是,当p和irr被传递时,将调用Polynomial的复制构造函数。

这只是部分正确。由于Polinomials是按值传递的,因此可能会复制(但复制省略可能意味着根本没有复制),但在FiniteFieldElement(int l, Polynomial p, Polynomial irr)内,Polynomial的复制赋值运算符将是假设this->pthis->irr属于Polynomial类型,则调用此方法。所以你的班级字段是作业的结果,而不是副本。

因此,您应该查看复制赋值运算符的实现。

答案 1 :(得分:1)

实际初始化多项式吗? 执行new int[degree_ + 1];不会构造初始化的数组,其值是垃圾。

编辑:除非您有另一个很好的理由需要int*,否则最好使用std::vector作为多项式系数容器。它将简化对象构造,破坏和分配。

这很有效(这意味着问题出在您未向我们展示的代码部分:类定义和赋值运算符)

class Polynomial
{
public:

    Polynomial();
    Polynomial( const Polynomial& p );
    template <int N> Polynomial(int (&Poly)[N] );

    Polynomial& operator=( const Polynomial& Rhs);

    void Print();

    ~Polynomial();
private:
    int* poly_;
    int degree_;
};

class FiniteFieldElement
{
public:
    FiniteFieldElement( Polynomial P );

    void Print();
private:
    Polynomial p_;
};

和实施:

Polynomial::Polynomial()
{
    degree_ = 0;
    poly_ = new int[degree_ + 1];

    poly_[0] = 1;
}

// excessive, you don't really need this
template <int N> Polynomial::Polynomial(int (&Poly)[N] )
{
    degree_ = N - 1;
    poly_ = new int[degree_ + 1];

    for (int i = 0; i <= degree_; i++)
    {
        poly_[i] = Poly[i];
    }
}

Polynomial& Polynomial::operator=( const Polynomial& Rhs)
{        
    if ( this != &Rhs )
    {
        degree_= Rhs.degree_;

        delete[] poly_;

        poly_ = new int[degree_ + 1];

        for (int i = 0; i <= degree_; i++)
        {
            poly_[i] = Rhs.poly_[i];
        }
    }

    return *this;
}


void Polynomial::Print()
{
    std::cout<< "Degree = " << degree_ << "\n Polynomial = ";
    for (int i = 0; i <= degree_; i++)
    {
        std::cout<< poly_[i] << " ";
    }
    std::cout<<"\n";
}

Polynomial::~Polynomial()
{
    delete[] poly_;
}

Polynomial::Polynomial(const Polynomial& p)
{
    degree_ = p.degree_;
    poly_ = new int[degree_ + 1];

    for (int i = 0; i <= degree_; i++)
    {
        poly_[i] = p.poly_[i];
    }
}

FiniteFieldElement::FiniteFieldElement( Polynomial P )
{
    p_ = P;
}

void FiniteFieldElement::Print()
{
    p_.Print();
}

主要是:

int main(int argc, _TCHAR* argv[])
{
    int myPoly[] = { 1, 2, 3 };

    Polynomial foo(myPoly);

    FiniteFieldElement bar( foo );

    std::cout<< "Foo:\n";
    foo.Print();
    std::cout<< "Bar:\n";
    bar.Print();

    return 0;
}

如果它适用于您的计算机,请在代码和行为中查看它与您的实现的不同之处。

答案 2 :(得分:0)

感谢大家,事实证明Eclipse CDT调试器给了我错误的值。 Visual Studio中的相同断点(或只是打印值[见下面的模数])给出了正确的答案。也许我没有正确使用它,但是当您在调试器中输入监视表达式时,您希望得到正确的值。

Eclipse CDT bug