三行法则——意外结果 我在空闲时间尝试学习C++基础,并跟着一本书练习。首先,当我输入9作为行,输入8作为列时,我得到malloc-freeing错误。其次,我得到0作为输出,我看不到我输入的内容。我想写这个程序,因为我可以强化三法则。这当然不是家庭作业。此外,我认为这是一个困难的问题和有效的问题。如果这个问题能得到回答,那将很有帮助。因为我在谷歌上搜索过,所以找不到这个解决方案的半点好处。另外,您可以检查我的复制构造函数、赋值运算符和析构函数,并告诉我错误在哪里吗

三行法则——意外结果 我在空闲时间尝试学习C++基础,并跟着一本书练习。首先,当我输入9作为行,输入8作为列时,我得到malloc-freeing错误。其次,我得到0作为输出,我看不到我输入的内容。我想写这个程序,因为我可以强化三法则。这当然不是家庭作业。此外,我认为这是一个困难的问题和有效的问题。如果这个问题能得到回答,那将很有帮助。因为我在谷歌上搜索过,所以找不到这个解决方案的半点好处。另外,您可以检查我的复制构造函数、赋值运算符和析构函数,并告诉我错误在哪里吗,c++,pointers,dynamic-memory-allocation,rule-of-three,C++,Pointers,Dynamic Memory Allocation,Rule Of Three,编写一个实现二维动态数组的类TwoD 在构造器中使用此显示的想法的双精度。你 应该有一个类型为pointer to double to point to的私有成员 动态数组,以及两个 MaxRows和MaxCols。您应该为其提供默认构造函数 您需要选择默认的最大行和列大小以及 允许程序员设置最大值的参数化构造函数 行和列的大小。此外,还应提供一个void成员 函数,该函数允许设置特殊的行和列条目以及 返回特定行和列条目作为 类型double的值。备注:这是困难的或不可能的 在详细信息上重载[]

编写一个实现二维动态数组的类TwoD 在构造器中使用此显示的想法的双精度。你 应该有一个类型为pointer to double to point to的私有成员 动态数组,以及两个 MaxRows和MaxCols。您应该为其提供默认构造函数 您需要选择默认的最大行和列大小以及 允许程序员设置最大值的参数化构造函数 行和列的大小。此外,还应提供一个void成员 函数,该函数允许设置特殊的行和列条目以及 返回特定行和列条目作为 类型double的值。备注:这是困难的或不可能的 在详细信息上重载[],使其按您所希望的方式工作 二维阵列。因此,只需使用访问器和mutator函数 使用普通函数表示法。将+运算符作为朋友重载 函数添加两个二维数组。这个功能应该 返回其第i行、第j列元素为 左侧操作数TwoD对象的第i行、第j列元素 以及右操作数TwoD的第i行、第j列元素 对象提供复制构造函数、重载运算符=、和 析构函数。声明不更改数据的类成员函数 作为康斯特成员

我的努力

#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;
}
复制构造函数创建数组,但从不复制内容。 “复制分配”操作符可以正确执行此操作。因此,您有大量重复的新[]循环,几个delete[]循环,并且您应该有两个copy循环。把这些因素分解成函数,你只需要一次就可以得到正确的结果

sum创建一个默认大小的对象,然后可能会超出行和列的维度。通常简单而正确的实现是使用上面固定的copy-ctor并转发到操作符+=,创建左手参数的本地副本。那个接线员更容易找对

你有办法把这些矩阵打印出来。做吧!到处都这样!这使得我们很容易看出在哪个阶段出了问题

这本书听起来不太好。没有明显的原因,它教的是不好的实践,操作符+技巧是标准的,如果你不能使用向量,你应该使用unique_ptr,等等

编辑:我会在这里回复一些评论,因为它们有变成聊天会话的危险,我不想在这上面花更多的时间

我有固定副本构造函数,对吗

现在是了解如何测试和调试代码的好时机。添加打印语句,使用调试器,将内容拆分为可以测试的函数,然后为它们编写测试

你指的是两个delete[]循环和两个copy循环

在代码中查找循环。我可以看到3个循环调用new[],它们基本上都在做相同的事情。我可以看到两个调用delete[]的循环,一个在析构函数中,另一个在复制赋值操作符中。只需在您自己的代码中搜索for关键字

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


那么TwoD::putArr来自哪里?诚然,您的代码存在以下问题:

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;

    ///
    /// This constructs a new TwoD object but does not change
    /// object on which the function was invoked.
    ///
    TwoD(MaxRows,MaxCols);    
}
并实施为:

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);

    // Now read the data.
    for (int i = 0; i < r_user; i++)
    {
        for (int j = 0; j < c_user; j++)
        {
            cout << "Enter for " << i << j << "=> ";
            cin  >> obj.arr[i][j];
        }
    }

    // Return the object
    return obj;
}

我们已经有一个很好的问答,关于如何正确实施和应用。你建议哪本书?这绝对是C++沃特萨维奇害怕书推荐是OT,反正我不知道什么水平投掷。只需从评论中的规则3链接开始,并进行您自己的研究。对于第一个规范,我有固定副本构造函数,对吗?还有一件事我不明白你所说的两个delete[]循环和两个copy循环是什么意思。你能解释一下吗?我已经有了析构函数。你拆掉dtor和赋值操作符中的数组,复制代码。将其移动到函数并从两个位置调用。分配数组也一样,复制值也一样。哦,对吗?试试看!打印结果,在调试器中逐步执行,看看它是否做了正确的事情。在应用您建议的方法后,谢谢您,我还尝试了复制构造函数我得到了内存错误。两个arr4arr3;。你介意帮忙吗?我更新了代码。@newbie,int I=0的行;i向上使用数组超出范围。它需要为int i=0;iTwoD::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]; } }
static TwoD constructFromUserInput();
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);

    // Now read the data.
    for (int i = 0; i < r_user; i++)
    {
        for (int j = 0; j < c_user; j++)
        {
            cout << "Enter for " << i << j << "=> ";
            cin  >> obj.arr[i][j];
        }
    }

    // Return the object
    return obj;
}
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;
   arr1.putArr();
   arr2.putArr();
   arr3.putArr();

   return 0;
}