Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.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++是比较陌生的,所以请原谅我的白痴。我试着自学如何使用运算符。我定义了一个非常基本的运算符,如下所示: Matrix::Matrix operator+(Matrix a1, Matrix a2) { if(a1.rows != a2.rows || a1.cols != a2.cols) { std::cout << "ERROR: Attempting to add matrices of non-equal size." << std::endl; exit(6); } int i, j; Matrix c(a1.rows, a1.cols); for(i = 0; i < a1.rows; i++) for(j = 0; j < a1.cols; j++) c.val[i][j] = a1.val[i][j] + a2.val[i][j]; return c; } Matrix operator +(Matrix a, Matrix b) { … }_C++_Operators - Fatal编程技术网

C++;运算符销毁输入变量 也许这只是我愚蠢的原因,但我对C++是比较陌生的,所以请原谅我的白痴。我试着自学如何使用运算符。我定义了一个非常基本的运算符,如下所示: Matrix::Matrix operator+(Matrix a1, Matrix a2) { if(a1.rows != a2.rows || a1.cols != a2.cols) { std::cout << "ERROR: Attempting to add matrices of non-equal size." << std::endl; exit(6); } int i, j; Matrix c(a1.rows, a1.cols); for(i = 0; i < a1.rows; i++) for(j = 0; j < a1.cols; j++) c.val[i][j] = a1.val[i][j] + a2.val[i][j]; return c; } Matrix operator +(Matrix a, Matrix b) { … }

C++;运算符销毁输入变量 也许这只是我愚蠢的原因,但我对C++是比较陌生的,所以请原谅我的白痴。我试着自学如何使用运算符。我定义了一个非常基本的运算符,如下所示: Matrix::Matrix operator+(Matrix a1, Matrix a2) { if(a1.rows != a2.rows || a1.cols != a2.cols) { std::cout << "ERROR: Attempting to add matrices of non-equal size." << std::endl; exit(6); } int i, j; Matrix c(a1.rows, a1.cols); for(i = 0; i < a1.rows; i++) for(j = 0; j < a1.cols; j++) c.val[i][j] = a1.val[i][j] + a2.val[i][j]; return c; } Matrix operator +(Matrix a, Matrix b) { … },c++,operators,C++,Operators,它给出了正确的结果,但是a和b不再可用,并且我在代码末尾得到了一个glibc错误,声称我试图在a和b已经被破坏时破坏它们。这是为什么?我假设您正在使用new在矩阵类中分配动态内存,并且没有实现自定义副本构造函数,因此违反了 然后,错误的原因是矩阵实例的本地副本重用了参数实例的动态内存,而它们的析构函数在方法末尾释放了它 解决方案非常简单:。相反,您可以使用嵌套的std::vector来存储数据 此外,操作员的头部被撞伤。根据声明函数的位置,如果在类中定义运算符,则函数必须如下所示: Return

它给出了正确的结果,但是a和b不再可用,并且我在代码末尾得到了一个glibc错误,声称我试图在a和b已经被破坏时破坏它们。这是为什么?

我假设您正在使用
new
矩阵
类中分配动态内存,并且没有实现自定义副本构造函数,因此违反了

然后,错误的原因是
矩阵
实例的本地副本重用了参数实例的动态内存,而它们的析构函数在方法末尾释放了它

解决方案非常简单:。相反,您可以使用嵌套的
std::vector
来存储数据

此外,操作员的头部被撞伤。根据声明函数的位置,如果在类中定义运算符,则函数必须如下所示:

ReturnType operator +(Arg1)
或者,如果在类之外定义它,它需要如下所示:

ReturnType operator +(Arg1, Arg2)
你的是两者的混合体。我假设您的运算符定义如下所示:

Matrix::Matrix operator+(Matrix a1, Matrix a2) {
    if(a1.rows != a2.rows || a1.cols != a2.cols) {
        std::cout << "ERROR: Attempting to add matrices of non-equal size." << std::endl;
        exit(6);
    }

    int i, j;

    Matrix c(a1.rows, a1.cols);

    for(i = 0; i < a1.rows; i++)
        for(j = 0; j < a1.cols; j++)
            c.val[i][j] = a1.val[i][j] + a2.val[i][j];

    return c;
}
Matrix operator +(Matrix a, Matrix b) { … }

如果您的代码进行编译,那么这可能是编译器中的错误,或者您确实使用了非常奇怪的类结构。此外,正如Luchian指出的,将参数作为
const&
传递比按值传递更有效。但是,您应该首先使代码正确运行。

您的签名错误:

Matrix operator+(Matrix a1, Matrix a2)
应该是

Matrix operator+(const Matrix& a1, const Matrix& a2)
它似乎销毁
a1
a2
的原因是,确实如此,因为这些是在方法范围内创建的临时副本

如果原始值被破坏,则可能违反了三条规则。当
a1
a2
被销毁时,将调用析构函数,您可能正在删除析构函数中的指针。但由于默认的复制构造函数只进行浅层复制,因此复制的
a2
a1
将删除原始内存

编辑:由于对此存在分歧,我将扩展我的答案: 假设:

struct A
{
   int* x;
   A() { x = new int; *x = 1; }
   ~A() { delete x; }
};

//option 1:
A operator + (A a1, A a2)
{
   A a; return a; //whatever, we don't care about the return value
}

//option 2:
A operator + (const A& a1, const A& a2)
{
   A a; return a; //again, we don't really care about the return value
}
在第一个示例中,没有实现复制构造函数

编译器生成一个复制构造函数。此复制构造函数将
x
复制到新实例中。因此,如果你有:

A a;
A b = a;
assert( a.x == b.x );
重要请注意指针是相同的

调用
选项1
将在
操作符+
内创建副本,因为值是按值传递的:

A a;
A b;
a + b; 
//will call:
A operator + (A a1, A a2)
// a1.x == a.x
// a2.x == n.x
operator+
退出时,它将对对象
a1
a2
调用
delete x
,这将删除
a.x
b.x
指向的内存。这就是为什么会出现内存损坏

调用
选项2
但是,由于通过引用传递不会创建新对象,因此函数返回时不会删除内存

然而,这并不是解决问题的最干净的方法。它解决了这个问题,但正如康拉德所指出的,根本问题更为重要,我在最初的回答中也提到了这一点(尽管我承认,我没有给予足够的重视)

现在,解决这个问题的正确方法是正确地遵循三个规则。也就是说,有一个
析构函数
复制构造函数
赋值运算符
的实现:

struct A
{
   int* x;
   A() { x = new int; *x = 1; }
   A(const A& other)  //copy constructor
   {
      x = new int;  // this.x now points to a different memory location than other.x
      *x = other.(*x);  //copy the value though
   }
   A& operator = (const A& other) //assignment operator
   { 
      delete x; //clear the previous memory
      x = new int;     
      *x = other.(*x);  //same as before
   }
   ~A() { delete x; }
};
有了这段新代码,让我们从前面重新运行有问题的
选项1

A a;
A b;
a + b; 
//will call:
A operator + (A a1, A a2)
// a1.x != a.x
// a2.x != n.x
因为拷贝
a1
a2
现在指向不同的内存位置,所以当它们被销毁时,原始内存是完整的,原始对象-
a
b
仍然有效


希望这能澄清问题。

因为矩阵的大小是在运行时给定的,所以我假设矩阵类包含一个指针,该指针由析构函数删除的动态分配数组初始化

在这种情况下,还必须定义复制构造函数和赋值运算符,以便分配矩阵所包含内容的副本


如果不这样做,默认的复制和赋值将只是重新分配指针,让您使用两个或多个矩阵来保存同一个数组。当其中一个被销毁(从而删除阵列)时,其他阵列仍然悬空。

正如Luchian Grigore指出的,您的签名是错误的,应该是:

矩阵运算符+(常数矩阵和a1、常数矩阵和a2)

但即使是这个签名本身也不应该破坏
a
b
。但因为你在抄袭论点,我有另一个怀疑

您是否定义了自己的复制构造函数?我认为,当您将旧变量的值复制到运算符的参数时,您可能正在删除它们


请共享您的复制构造函数(最好是operator=和在此运算符中使用的两参数构造函数)

此代码甚至不应编译,它缺少返回类型。请发布正确的代码,以及
Matrix
类的最低版本(但需要编译),特别是显示构造函数、复制构造函数和析构函数!这段代码不编译。。。我复制粘贴了代码。我不确定你所说的缺少返回类型是什么意思,它返回类矩阵中的一些东西,因为它被定义为矩阵::矩阵运算符+(…),对吗?你遵循三个规则吗?我的解释是,您正在动态分配内存,并且(可能)在析构函数中释放内存。如果是,您是否提供了复制构造函数和赋值运算符?如果不是,您的问题可能是正在复制参数,但只复制指针