三法则运动出乎意料的结果 [英] rule of three exercise unexpected result

查看:112
本文介绍了三法则运动出乎意料的结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试在业余时间学习C ++基础并按照书中的练习进行学习。首先,当我输入9作为行,输入8作为列时,我得到了malloc释放错误。其次,我的输出为0,看不到输入的内容。我想编写该程序,因为我可以加强三个规则。当然不是功课。此外,我认为这是一个困难的问题和有效的问题。如果问题可以得到解答,将很有帮助。因为我已经在Google上进行搜索,所以找不到关于解决方案的正当做法。另外,您可以检查我的复制构造函数,赋值运算符和析构函数,并告诉我我的错误在哪里吗?

I try to learn C++ basis in my free time and follow exercises of a book. Firstly, when I enter 9 as row and 8 as column I get malloc freeing error. Secondly, I get 0 as output I can't see what I enter. I want to write the program because I can reinforce rule of three. It's certainly not homework. Besides, I think it is hard question and efficient question. If the question can be answered, it will be helpful. Because I've searched on google I can't find out halfway decent thing about solution. Also, can you check my copy constructor, assignment operator and destructor and tell me where my errors at?


编写一个实现了二维动态数组
使用其构造函数中显示的内容进行加倍。您
应该有一个类型为double的私有成员,以指向
动态数组,以及两个int(或无符号int)值,即
MaxRows和MaxCols。您应该提供一个默认的构造函数,您要为其选择
的默认最大行和列最大大小,以及一个
参数化的构造函数,该构造函数允许程序员设置最大
的行和列大小。此外,您应该提供一个void成员
函数,该函数允许设置特定的行和列条目,以及一个
成员函数,该函数将特定的行和列条目返回为double类型的
值。 。备注:重载[]很难或不可能(取决于
),因此它可以像
二维数组那样工作。因此,只需使用普通函数符号使用访问器和更改器函数
即可。作为朋友的
函数重载+运算符以添加两个二维数组。此函数应该
返回TwoD对象,其第i行第j列元素是左侧操作数TwoD对象
的第i行第j列元素和第ith行的
之和,右侧操作数TwoD
对象的第j个列元素。提供一个副本构造函数,一个重载的运算符=和一个
析构函数。将不更改数据
的类成员函数声明为const成员。

Write a class TwoD that implements the two-dimensional dynamic array of doubles using ideas from this display in its constructors. You should have a private member of type pointer to double to point to the dynamic array, and two int (or unsigned int) values that are MaxRows and MaxCols. You should supply a default constructor for which you are to choose a default maximum row and column sizes and a parameterized constructor that allows the programmer to set maximum row and column sizes. Further, you should provide a void member function that allows setting a particu- lar row and column entry and a member function that returns a particular row and column entry as a value of type double. Remark: It is difficult or impossible (depending on the details) to overload [ ] so it works as you would like for two-dimensional arrays. So simply use accessor and mutator functions using ordinary function notation. Overload the + operator as a friend function to add two two-dimensional arrays. This function should return the TwoD object whose ith row, jth column element is the sum of the ith row, jth column element of the left-hand operand TwoD object and the ith row, jth column element of the right-hand operand TwoD object. Provide a copy constructor, an overloaded operator =, and a destructor. Declare class member functions that do not change the data as const members.

我的努力

#include <iostream>
using std::cin;
using std::cout;
using std::endl;

class TwoD
{
public:
    TwoD();
    TwoD(int row, int column);
    void setRowCol();
    double getVal(int row, int column);
    friend const TwoD operator +(const TwoD& first, const TwoD& second);
    int getterRow() const;
    int getterCol() const;
    void setterRow(int row);
    void setterCol(int column);
    TwoD(const TwoD& object);
    TwoD& operator =(const TwoD& rightSide);
    void putArr() const;
    ~TwoD();
    static TwoD constructFromUserInput();
private:
    int MaxRows;
    int MaxCols;
    double **arr;
};

int main(int argc, char const *argv[])
{
    cout << "All size of TwoD object must be same\n\n";

    TwoD arr1 = TwoD::constructFromUserInput();
    TwoD arr2 = TwoD::constructFromUserInput();

    TwoD arr3;

    arr3 = arr1 + arr2;

    TwoD arr4(arr3);
    arr1.putArr();
    arr2.putArr();
    arr3.putArr();
    arr4.putArr();

    return 0;
}
void TwoD::setRowCol()
{
    int r_user;
    int c_user;
    cout << "Enter num of rows => ";
    cin  >> r_user;
    cout << "Enter num of columns => ";
    cin  >> c_user;

    MaxRows = r_user;
    MaxCols = c_user;

    TwoD(MaxRows,MaxCols);

}
TwoD::TwoD(int row, int column)
: MaxRows(row), MaxCols(column)
{
    arr = new double*[row];
    for (int i = 0; i < row; i++)
    {
        arr[i] = new double[column];
    }

    for (int i = 0; i < MaxRows; i++)
    {
        for (int j = 0; j < MaxCols; j++)
        {
            cout << "Enter for " << i << j << "=> ";
            cin  >> arr[i][j];
        }
    }
}
TwoD::TwoD()
: MaxRows(2), MaxCols(2)
{
    arr = new double*[2];
    for (int i = 0; i < 2; i++)
    {
        arr[i] = new double[2];
    }
}
double TwoD::getVal(int row, int column)
{
    return arr[row][column];
}
const TwoD operator +(const TwoD& first, const TwoD& second)
{
    TwoD sum;
    for (int i = 0; i < first.MaxRows; i++)
    {
        for (int j = 0; j < first.MaxCols; j++)
        {
            sum.arr[i][j] = first.arr[i][j] + second.arr[i][j];
        }
    }
    return sum;
}
TwoD::TwoD(const TwoD& object)
{
    MaxRows = object.MaxRows;
    MaxCols = object.MaxCols;

    arr = new double*[MaxRows];
    for (int i = 0; i < MaxRows; i++)
    {
        arr[i] = new double[MaxCols];
    }

    for ( int i = 0; i < MaxRows; i++ )
    {
        for ( int j = 0; j < MaxCols; j++ )
        {
            arr[i][j] = object.arr[i][j];
        }
    }
}
TwoD::~TwoD()
{
    for (int i = 0; i < MaxRows; i++)
        delete [] arr[i];
    delete [] arr;
}
TwoD& TwoD::operator =(const TwoD& rightSide)
{
    if (this == &rightSide)
    {
        return *this;
    }

    for (int i = 0; i < MaxRows; i++)
        delete [] arr[i];
    delete [] arr;

    arr = new double*[rightSide.MaxRows];
    for (int i = 0; i < rightSide.MaxRows; i++)
    {
        arr[i] = new double[rightSide.MaxCols];
    }

    MaxRows = rightSide.MaxRows;
    MaxCols = rightSide.MaxCols;

    for (int i = 0; i < MaxRows; i++)
    {
        for (int j = 0; j < MaxCols; j++)
        {
            arr[i][j] = rightSide.arr[i][j];
        }
    }
    return *this;
}
void TwoD::putArr() const
{
    for (int i = 0; i < MaxRows; i++)
    {
        for (int j = 0; j < MaxCols; j++)
        {
            cout << arr[i][j] << " ";
        }
        cout << endl;
    }
}
int TwoD::getterRow() const
{
    return MaxRows;
}
int TwoD::getterCol() const
{
    return MaxCols;
}
void TwoD::setterRow(int row)
{
    MaxRows = row;
}
void TwoD::setterCol(int column)
{
    MaxCols = column;
}
TwoD TwoD::constructFromUserInput()
{
    int r_user;
    int c_user;
    cout << "Enter num of rows => ";
    cin  >> r_user;
    cout << "Enter num of columns => ";
    cin  >> c_user;

    // Construct an object.
    TwoD obj(r_user, c_user);

    // Return the object
    return obj;
}


推荐答案


  1. 您的复制构造函数创建数组,但从不复制内容。
    复制分配运算符可以正确执行此操作。为此,您有大量重复的 new [] 循环,几个 delete [] 循环,并且您应该具有两个复制循环。将这些因素分解为函数,您只需要将它们正确处理一次即可。

  1. your copy constructor creates the arrays, but never copies the contents. The copy assignment operator does this correctly. For that matter, you have loads of duplicated new[] loops, a couple of delete[] loops, and you should have two copy loops. Factor these out into functions, and you only need to get them right once.

sum 创建一个默认大小对象,然后可能会超出行和列的尺寸。通常的(简单而正确的)实现是创建左手参数的本地副本(使用您在上面固定的副本ctor)并转发到 operator + = 。该运算符更容易正确设置。

sum creates a default-sized object and then, probably, overruns both row and column dimensions. The usual (easy and correct) implementation is to create a local copy of the left-hand argument (using the copy ctor you fixed above) and forward to operator+=. That operator is much easier to get right.

您可以打印出这些矩阵。做吧!随处做!这样可以很容易地看出问题出在哪个阶段。

you have a way of printing these matrices out. Do it! Do it everywhere! This makes it easy to see which stage things went wrong at.

这本书听起来不太好。这是没有明显原因的教学实践(operator +技巧是标准的,如果不能使用 vector unique_ptr c>等)

this book doesn't sound very good. It's teaching poor practice for no obvious reason (the operator+ trick is standard, you should use unique_ptr if you can't use vector, etc. etc.)






编辑:我是ll在此处回复一些评论,因为它们有变成聊天会话的危险,我不想在此花费更多时间。


Edits: I'll reply to some comments here because they're in danger of turning into a chat session, and I don't want to spend more time on this.



我有固定副本构造函数吗?

I have fixed copy constructor is it right?

这很好是时候弄清楚如何测试和调试代码了。添加打印语句,使用调试器,将其分解成可以测试的功能,然后为它们编写测试。

This is a good time to figure out how to test and debug code. Add print statements, use a debugger, split things out into functions you can test and then write tests for them.


表示几个 delete [] 循环和两个复制循环

看代码中的循环。我可以看到3个调用 new [] 的循环,它们基本上都在做同样的事情。我可以看到2个调用 delete [] 的循环,一个在析构函数中,另一个在拷贝赋值运算符中。只需在您自己的代码中搜索 for 关键字!

Look for loops in your code. I can see 3 loops calling new[], all doing essentially the same thing. I can see 2 loops calling delete[], one in the destructor and one in the copy assignment operator. Just search your own code for the for keyword!


我真的找不到打印矩阵的方法

I really don't find a way to print out matrices

所以 TwoD :: putArr 来自哪里?承认 ostream&运算符<<(ostream& ;, TwoD const&)会是一个更好的名称,但是您写了它,所以不妨使用它。

so where did TwoD::putArr come from? Admittedly ostream& operator<<(ostream&, TwoD const &) would be a better name for it, but you wrote it so you might as well use it.


我无法将析构函数放入main()

I can't get destructor into main()

您不能停止在main完成时调用析构函数-然后您的对象超出范围。只需在析构函数中插入一个断点,它将被调用。

you can't stop the destructor being called when main finishes - your objects go out of scope then. Just stick a breakpoint in the destructor and it will be called.


因为arr是私有的,我该如何测试?

Because arr is private how can I test?

您仍然可以在调试器中看到它,仍然可以打印内容(如上所述),仍然可以调用从单元测试中获取getVal ,只需将其设为公开,直到找出问题所在

you can still see it in the debugger, you can still print the contents (as above), you can still call getVal from a unit test, you can just make it public until you've figured out your problem(s)

这篇关于三法则运动出乎意料的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆