【问题标题】:overloading = operator in a class for a dynamic array C++在类中为动态数组 C++ 重载 = 运算符
【发布时间】:2013-09-11 20:14:12
【问题描述】:

我一直在尝试添加两个二维数组。在我为“=”添加重载函数后,C++ 开始崩溃一次。编译器只是崩溃。但是没有添加

cout << "combining the two is" << endl;
example3 = example1 + example2;
example3.outPut();

并禁用重载运算符成员函数,一切正常。
你能帮忙吗?

enter code here

#include <iostream>
using namespace std;
#include <string>
#include <fstream>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <vector>
#include <windows.h>
#include <cstring>
#include <cctype>
#include <iomanip>
#include <algorithm>
#include<sstream>


class TwoD
{
private:
int MaxRows;
int MaxCols;
double** outerArray;

public:
TwoD(int maxRows, int maxCols)
{
    MaxRows = maxRows;
    MaxCols = maxCols;
    outerArray = new double *[MaxRows];
    for (int i = 0; i < MaxRows; i++)
        outerArray[i] = new double[MaxCols];
}

void input()
{
    for (int k = 0; k < MaxRows; k++)
        for (int j = 0; j < MaxCols; j++)
            cin >> outerArray[k][j];
}

void outPut()
{
    for (int l = 0; l < MaxRows; l++)
    {
        for (int m = 0; m < MaxCols; m++)
            cout << outerArray[l][m] << " ";
        cout << endl;
    }
}

const TwoD operator = (const TwoD& rightSide)
{
    for (int l = 0; l < MaxRows; l++)
    {
        for (int m = 0; m < MaxCols; m++)
            outerArray[l][m] = rightSide.outerArray[l][m];
        cout << endl;
    }

    return *this;
}



const TwoD operator + (const TwoD& rightSide)
{
    for (int l = 0; l < MaxRows; l++)
    {
        for (int m = 0; m < MaxCols; m++)
            outerArray[l][m] = outerArray[l][m] + rightSide.outerArray[l][m];
        cout << endl;
    }

    return *this;
}

~TwoD()
{
    for (int i = 0; i < MaxRows; i++)
        delete[] outerArray[i];
    delete[] outerArray;
}

};

int main()
{
TwoD example1(3, 3), example2(3,3), example3(3,3);
cout << "input example1" << endl;
example1.input();
example1.outPut();

cout << "input example2" << endl;
example2.input();
example2.outPut();

cout << "combining the two is" << endl;
example3 = example1 + example2;
example3.outPut();


return 0;
}

【问题讨论】:

  • 你能说得更具体点吗?有什么问题吗.....const TwoD operator = (const TwoD& rightSide)
  • 又错了,不过还是&amp;
  • 运算符 = 不应按值返回。这会创建一个毫无意义的副本。通过非常量引用返回是标准做法。您还需要一个复制构造函数。

标签: c++ arrays


【解决方案1】:

编译器崩溃了。

真的吗?对我来说,程序可以编译,但由于双重删除而在运行时崩溃。

你能帮忙吗?

要使类正确可复制:

  • 根据Rule of Three,您需要一个复制构造函数和一个复制赋值运算符。您只有赋值运算符。
  • 赋值运算符应该返回一个引用,而不是一个副本。

一个合适的复制构造函数可能看起来像

TwoD(const TwoD& other) : TwoD(other.MaxRows, other.MaxCols)
{
    for (int l = 0; l < MaxRows; l++)
        for (int m = 0; m < MaxCols; m++)
            outerArray[l][m] = other.outerArray[l][m];    
}

(如果您不能使用 C++11 的委托构造函数,那么您需要复制默认构造函数的初始化,或者将其移到两个构造函数调用的单独函数中)。

一旦有了复制构造函数,您可能会考虑使用copy-and-swap idiom 来获得对异常更友好的赋值运算符。在 C++11 中,您还可以考虑使类可移动(通过将指针复制到目标,并使受害者中的指针无效),以避免在某些情况下进行不必要的内存分配。

另外,operator+ 不应该修改它的参数;它应该返回一个新创建的对象。你的实现更适合operator+=(虽然,像operator=,它应该返回一个引用,而不是一个副本)。

一旦您了解了手动内存管理的工作原理,您应该使用标准容器和智能指针等类来为您解决所有这些繁琐的问题。特别是,std::vector 是一个动态数组。

【讨论】:

  • 感谢您的指导。我想我学到了我需要做的事情。你解释的有道理,我需要做更多的研究来巩固我的理解。我想改天使用向量,现在更好地理解“复制构造函数”。 ——
  • 迈克,我还在挣扎。我昨天不得不去上班,我以为你的评论会解决它。但它没有。你能看看我的问题吗....stackoverflow.com/questions/18738504/…
【解决方案2】:

对于动态分配内存的class/struct,需要关注rule of three

class TwoD
{
public:
   TwoD(const TwoD& other);             // copy constructor
   TwoD& operator = (const TwoD& other) // copy assign operator
};

我建议你使用vectorvector 来表示二维数组,你甚至不需要编写复制构造、内存管理等。

#include <vector>
struct TwoD
{
    std::vector<std::vector<double> > outerarray;
};

【讨论】:

    【解决方案3】:

    前面的回答错了,让我再试一下。

    当您创建对象的副本时,您的矩阵不会被复制,只有指向它的指针被复制。这意味着您有多个对象,特别是这里的临时对象,当它们被破坏时,将删除矩阵,然后在函数结束时,您将再次删除它们。这是你的崩溃,双重免费。

    您需要定义一个“复制构造函数”,它会以一种彬彬有礼的方式制作您的对象的真实副本,这就是 Billz 所指的,或者采取简单的方法并使用 C++ 库类,如 vector为你处理好这个。

    int MaxRows;
    int MaxCols;
    double** outerArray;
    

    会变成

    std::vector<std::vector<double> > matrix = new std::vector(MaxRows, new std::vector(MaxCols, 0.0))
    

    你可以在谷歌或http://en.cppreference.com/w/cpp/container/vector阅读更多关于vector的信息

    【讨论】:

    • 我一定不理解“return *this;”部分很好。我是对的吗?抱歉,我对 C++ 还很陌生,找不到任何在线答案。
    • operator= 按值返回不会调用自身,而是调用复制构造函数。不会有堆栈溢出。
    • @interjay 是的,你是对的.. 这就是问题所在,没有用户定义的复制构造函数..
    • 感谢您的指导。我想我学到了我需要做的事情。你解释的有道理,我需要做更多的研究来巩固我的理解。我想改天使用向量,现在更好地理解“复制构造函数”。
    • @UjaeKang 很高兴我们能帮到你!
    猜你喜欢
    • 1970-01-01
    • 2015-06-04
    • 2021-07-02
    • 1970-01-01
    • 2021-08-18
    • 1970-01-01
    • 2015-02-18
    • 2016-08-30
    • 1970-01-01
    相关资源
    最近更新 更多