Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/drupal/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么此对象未按值复制_C++ - Fatal编程技术网

C++ 为什么此对象未按值复制

C++ 为什么此对象未按值复制,c++,C++,当我在operator*函数中返回object temp时,它不会被复制到main中的p3 运算符*函数中的cout语句返回正确的值,但main中的p3只有垃圾 我还在main的return0语句中得到一个_block_type_is valid(phead->nblockuse) 这是代码 #pragma once #include<iostream> using namespace std; class Polynomial { private: int *coeffic

当我在operator*函数中返回object temp时,它不会被复制到main中的p3

运算符*函数中的cout语句返回正确的值,但main中的p3只有垃圾

我还在main的return0语句中得到一个_block_type_is valid(phead->nblockuse)

这是代码

#pragma once
#include<iostream>
using namespace std;
class Polynomial
{
private:
    int *coefficients;
    int length;
public:
    inline int getLength() const {return length;}
    Polynomial(int length);
    Polynomial(const Polynomial &p);
    Polynomial():coefficients(nullptr){}
    ~Polynomial(void);
    extern friend Polynomial operator*(const Polynomial &p1,const Polynomial &p2);
    inline int operator[](int n) const { return coefficients[n];}
    inline int& operator[](int n) { return coefficients[n];}
    Polynomial& operator=(Polynomial &p);
    friend void swap(Polynomial& first, Polynomial& second);
    void resize(int x);

    friend istream& operator>>(istream &is, Polynomial &p);
    friend ostream& operator<<(ostream &os, Polynomial &p);
};
#pragma一次
#包括
使用名称空间std;
类多项式
{
私人:
int*系数;
整数长度;
公众:
内联int getLength()常量{return length;}
多项式(整数长度);
多项式(常数多项式&p);
多项式():系数(nullptr){}
~多项式(空);
外部友元多项式算子*(常数多项式和p1,常数多项式和p2);
内联int运算符[](int n)常量{返回系数[n];}
内联int&运算符[](int n){返回系数[n];}
多项式&算子=(多项式&p);
朋友无效交换(多项式与第一、多项式与第二);
无效调整大小(int x);
friend istream&operator>>(istream&is,多项式&p);
friend ostream&operator假设它可以编译

你没有复制构造函数,这不是一个好主意。如果你实现了析构函数,你可能需要分配复制交换移动函数

另外,最好使用
std::vector
而不是动态分配,因为它会自动实现这些行为,并且编译器生成的构造函数就足够了

在您的情况下,返回将创建一个浅层副本(自动生成的副本cstr),但在函数返回后,原始副本将被销毁(已分配浅层副本引用的内存),并释放内存

这就足够了:

class Polynomial
{
private:
    std::vector<int> coefficients;

public:
    inline int getLength() const { return coefficients.size(); };
    Polynomial(int length): coefficients(length, 0) {};
    Polynomial operator*(const Polynomial& p); //you are not modifying p, thus const ref can work

    extern friend istream& operator>>(istream &is, Polynomial &p);
    extern friend ostream& operator<<(ostream &os, Polynomial &p);
};
类多项式
{
私人:
std::向量系数;
公众:
内联int getLength()常量{返回系数.size();};
多项式(整数长度):系数(长度,0){};
多项式运算符*(常数多项式&p);//您没有修改p,因此常数ref可以工作
extern friend istream&operator>>(istream&is,多项式&p);
外部友元ostream&算子(istream&is,多项式&p);

如果你用正确的标志调用你的编译器,这个代码就不能编译。<强>没有C++编译器,它使用默认标志工作得很好!< /强>

例如,让我们使用这样的调用,使用一些非默认标志:VisualC++ 2013:< /P>

cl /nologo /EHsc /Za /W4 stackoverflow.cpp
正确地说,结果是编译器错误:

stackoverflow.cpp(78) : error C2679: binary '=' : no operator found which takes a right-hand operand of type 'Polynomial' (or there is no acceptable conversion)

        stackoverflow.cpp(19): could be 'void Polynomial::operator =(Polynomial &)'
        while trying to match the argument list '(Polynomial, Polynomial)'
现在,让我们看看如果删除禁用Microsoft扩展的
/Za
标志会发生什么:

cl /nologo /EHsc /W4 stackoverflow.cpp
错误消失。但是,会出现一条警告:

warning C4239: nonstandard extension used : 'argument' : conversion from 'Polynomial' to 'Polynomial &'
        A non-const reference may only be bound to an lvalue; assigment operator takes a reference to non-const
最后,让我们看看如果我们删除警告级别标志
/W4
,编译器会做什么:

cl /nologo /EHsc stackoverflow.cpp

没有错误,没有警告。这是坏的。<代码> P3=(P1*P2); >不是标准C++。即使你可以VisualC++编译代码,也不会有什么好的。 派遣操作员的正确签名应为:

Polynomial& Polynomial::operator=(Polynomial const& p);
但是,您的代码最大的问题是使用了
new[]
delete[]
。您肯定在某个地方存在内存泄漏(构造和分配都分配,但只有析构函数删除),更糟糕的是,您多次删除同一数组

将以下输出添加到析构函数:

Polynomial::~Polynomial(void){
    std::cout << "coefficients address destructor: " << coefficients << "\n";
    delete[] coefficients;
}
三次
00463BF8
!这是未定义的行为,可能导致程序中发生任何可以想象的事情

但这怎么可能呢

答案是您的
操作符*
返回
多项式
对象的浅层副本。内部的指针被复制,最后两个指针指向相同的分配内存

您需要一个复制构造函数。您必须遵守所谓的三个规则:如果您需要实现复制构造函数、复制赋值运算符和析构函数中的一个,那么您需要实现所有这些

尽管如此,与其费尽心机手动执行动态分配,还不如帮自己一个忙,用
std::vector
代替指针和长度变量:

class Polynomial
{
private:
    std::vector<int> coefficients;
    // ...
};

最后,我认为您误解了
extern
。您不需要它来使用
friend
函数。只需从代码中删除它,否则GCC甚至不会编译它

下面是一个包含最重要修复的完整示例:

#include <iostream>
#include <vector>

using namespace std;

class Polynomial
{
private:
    std::vector<int> coefficients;
public:
    inline int getLength() const {return coefficients.size();}
    Polynomial(int length);
    Polynomial(){}
    Polynomial operator*(Polynomial &p);
    inline int operator[] (int n) const { return coefficients[n];}
    inline int& operator[] (int n) { return coefficients[n];}

    friend istream& operator>>(istream &is, Polynomial &p);
    friend ostream& operator<<(ostream &os, Polynomial &p);
};

Polynomial::Polynomial(int length) :
    coefficients(length)
{
    for(int i = 0; i < length; i++){
        coefficients[i] = 0;
    }
}

Polynomial Polynomial::operator*(Polynomial &p){
    Polynomial temp(coefficients.size() + p.getLength());

    for(int i = 0; i < coefficients.size(); i++){
        for(int j = 0; j < coefficients.size(); j++){
            temp[i+j] += coefficients[i] * p[j];            
        }
    }   
    cout<<temp;
    return temp;
}

istream& operator>>(istream &is,Polynomial &p){
    cout<<"Enter length: ";
    int length;
    is>>length;
    p.coefficients.clear();
    p.coefficients.resize(length);
    for(int i = 0; i < length; i ++)
        is>>p.coefficients[i];  
    return is;
}
ostream& operator<<(ostream &os,Polynomial &p){ 
    for(int i = 0; i < p.coefficients.size(); i ++)
        if(p.coefficients[i])
            os<<p.coefficients[i]<<"x^"<<i<<" ";        
    return os;
}

int main(){
    Polynomial p1,p2,p3;
    cin>>p1>>p2;
    p3 = (p1 * p2);

    cout<<p3[0]<<p3[1]<<"here";
    cout<<p3;

    return 0;
}
#包括
#包括
使用名称空间std;
类多项式
{
私人:
std::向量系数;
公众:
内联int getLength()常量{返回系数.size();}
多项式(整数长度);
多项式(){}
多项式算子*(多项式&p);
内联int运算符[](int n)常量{返回系数[n];}
内联int&运算符[](int n){返回系数[n];}
friend istream&operator>>(istream&is,多项式&p);
friend-ostream&算子系数[i];
回报是;
}

ostream&operator不确定它如何编译为
operator=
引用和
(p1*p2)
返回一个不会绑定到非常量引用的临时对象。同时更改
运算符*
运算符=
以获取常量引用并进行尝试。另外
运算符*
可能不应该是成员函数。当您按值返回对象时,如乘法运算符,将创建一个临时对象,然后删除结构化。你认为这个临时对象中的指针会发生什么情况?它会被复制,然后在临时对象被销毁时被删除。那么复制现在指向什么呢?你需要遵守。你说的是垃圾值,但这段代码甚至不应该编译。
错误C2679:binary'=':找不到使用righ的运算符“多项式”类型的t手操作数
GCC不会编译此操作数。我使用的是visual studio。我不能在这两种类型中使用常量多项式
Polynomial& Polynomial::operator=(Polynomial const& p);
Polynomial::~Polynomial(void){
    std::cout << "coefficients address destructor: " << coefficients << "\n";
    delete[] coefficients;
}
Enter length: 2
100
200
Enter length: 3
100
200
300
10000x^0 40000x^1 40000x^2 coefficients address destructor: 00463BF8
coefficients address destructor: 00463BF8
1040000herecoefficients address destructor: 00463BF8
class Polynomial
{
private:
    std::vector<int> coefficients;
    // ...
};
inline int operator[] (int n) const { return coefficients[n];}
inline int& operator[] (int n) { return coefficients[n];}
#include <iostream>
#include <vector>

using namespace std;

class Polynomial
{
private:
    std::vector<int> coefficients;
public:
    inline int getLength() const {return coefficients.size();}
    Polynomial(int length);
    Polynomial(){}
    Polynomial operator*(Polynomial &p);
    inline int operator[] (int n) const { return coefficients[n];}
    inline int& operator[] (int n) { return coefficients[n];}

    friend istream& operator>>(istream &is, Polynomial &p);
    friend ostream& operator<<(ostream &os, Polynomial &p);
};

Polynomial::Polynomial(int length) :
    coefficients(length)
{
    for(int i = 0; i < length; i++){
        coefficients[i] = 0;
    }
}

Polynomial Polynomial::operator*(Polynomial &p){
    Polynomial temp(coefficients.size() + p.getLength());

    for(int i = 0; i < coefficients.size(); i++){
        for(int j = 0; j < coefficients.size(); j++){
            temp[i+j] += coefficients[i] * p[j];            
        }
    }   
    cout<<temp;
    return temp;
}

istream& operator>>(istream &is,Polynomial &p){
    cout<<"Enter length: ";
    int length;
    is>>length;
    p.coefficients.clear();
    p.coefficients.resize(length);
    for(int i = 0; i < length; i ++)
        is>>p.coefficients[i];  
    return is;
}
ostream& operator<<(ostream &os,Polynomial &p){ 
    for(int i = 0; i < p.coefficients.size(); i ++)
        if(p.coefficients[i])
            os<<p.coefficients[i]<<"x^"<<i<<" ";        
    return os;
}

int main(){
    Polynomial p1,p2,p3;
    cin>>p1>>p2;
    p3 = (p1 * p2);

    cout<<p3[0]<<p3[1]<<"here";
    cout<<p3;

    return 0;
}