在C++中,当指向删除和指向不同对象时,分段故障指针



我开始使用C++中的指针,我觉得我一定缺少C和C++之间的一个关键元素。

我在一个类中有一个成员函数,它进行比较,然后更改指针指向的内容:

void thisClass::largerSmallerSetter(int leftSize, int rightSize, matrix& leftMatrix, matrix& rightMatrix, matrix* largermatrix, matrix* smallerMatrix)
{
if(leftSize >= rightSize)
{
*largermatrix = leftMatrix;
*smallerMatrix = rightMatrix;
}
else
{
*largermatrix = rightMatrix;
*smallerMatrix = leftMatrix;
}
}

最初我的电话是:

matrix* largerSized = nullptr;
matrix* smallerSized =  nullptr;
largerSmallerSetter(LeftMatrix.getNumPieces(), RightMatrix.getNumPieces(), leftMemory, rightMemory, largerSized, smallerSized);

这会产生一个错误。这是由于largerSize和smallerSize居住在0x0地址。

所以我想我应该确保指针是用初始化的。

matrix* largerSized = new matrix();
matrix* smallerSized = new matrix();

然而,这个新矩阵是完全无用的,所以我想去掉实际的"新矩阵",我只想让指针指向现有的矩阵。所以我添加了删除调用来删除对象。当我试图将指针重新分配给另一个对象时,会出现seg错误。

现在在C中,当我用malloc创建一个指针时,我可以释放那个指针。指针仍然存在,我可以指向其他地方。

有没有一种方法可以在不创建一堆只会挂在内存中并成为内存泄漏的对象的情况下实现我想要的东西?

我考虑过使用std::shared_ptr。但当我重新分配指针时,我担心当它到达范围的末尾时,它会试图删除我所指向的对象,该对象是在更高的范围内创建的,需要继续存在。所以我不一定对智能指针感兴趣。

我试过的另一件事是:

void thisClass::largerSmallerSetter(int leftSize, int rightSize, matrix& leftMatrix, matrix& rightMatrix, matrix* largermatrix, matrix* smallerMatrix)
{
if(leftSize >= rightSize)
{
largermatrix = &leftMatrix;
smallerMatrix = &rightMatrix;
}
else
{
largermatrix = &rightMatrix;
smallerMatrix = &leftMatrix;
}
}

但所有这些都是,当作用域结束时,传入的指针会回到调用函数之前的状态。

让我们看看您的代码是做什么的。

*largermatrix = leftMatrix;

它取消引用largermatrix(从而获得指针指向的内存),并尝试使用赋值运算符用leftMatrix的内容填充它(如果该运算符有自定义重载,则可以是自定义操作)。因此,如果largermatrix不指向任何内容,您将得到您描述的问题。

另一方面,

largermatrix = &leftMatrix;

这将指定largermatrix指向leftMatrix的位置,这正是您想要的。但是,由于largermatrix是一个局部变量,因此更改不会传播到调用者。因此,largermatrix应该是对指针的引用。

void thisClass::largerSmallerSetter(int leftSize, int rightSize, 
matrix& leftMatrix, matrix& rightMatrix,
matrix*& largermatrix, matrix*& smallerMatrix)

顺便说一句,很好的做法是,函数不会改变的其他通过引用的参数是常量引用,比如:

void thisClass::largerSmallerSetter(int leftSize, int rightSize, 
const matrix& leftMatrix, const matrix& rightMatrix, 
matrix*& largermatrix, matrix*& smallerMatrix)

我在一个类中有一个成员函数,它进行比较,然后更改指针指向的内容

否,您有一个分配给指针指向的对象的函数。在这种情况下,*运算符取消引用产生所指向对象的指针。如果指针没有指向对象,则其行为是未定义的。

但所有这些都是,当作用域结束时,传入的指针会回到调用函数之前的状态。

否,传递给函数的原始指针从未更改。指针是对象,与所有对象一样,默认情况下通过值传递。这意味着,例如,largerSizedlargermatrix是完全独立的对象。它们之间唯一的关系是,当您调用函数时,它们最初具有相同的值。更改largermatrix的值不会修改largerSized的值。如果你想让函数中的赋值修改传递的对象,你需要传递一个引用:

void thisClass::largerSmallerSetter(int leftSize, int rightSize,
matrix& leftMatrix, matrix& rightMatrix,
matrix*& largermatrix, matrix*& smallerMatrix)
// passed by reference --------------------^----------------------^

注意:这也适用于C。C没有引用,但您需要传递一个指向指针的指针,以便从函数中修改调用范围中的指针。

有多种方法可以用来比较两个矩阵:

  1. 更好的选择是返回最小矩阵的地址。例如,

    matrix *thisClass::largerSmallerSetter(int leftSize, int rightSize, matrix& leftMatrix, matrix& rightMatrix)
    {
    if(leftSize >= rightSize)
    return &rightMatrix;
    return &leftMatrix;
    }
    
  2. 您可以在C++中重载compasion运算符

    bool operator<(const matrix& a, const matrix& b)
    {
    return a.getNumPieces() < b.getNumPieces();
    }
    
  3. 您可以在C++中使用指针对指针。

    void thisClass::largerSmallerSetter(int leftSize, int rightSize, matrix& leftMatrix, matrix& rightMatrix, matrix** largermatrix, matrix** smallerMatrix)
    {
    if(leftSize >= rightSize)
    {
    *largermatrix = &leftMatrix;
    *smallerMatrix = &rightMatrix;
    }
    else
    {
    *largermatrix = &rightMatrix;
    *smallerMatrix = &leftMatrix;
    }
    }
    
  4. 您可以引用指针。

    void thisClass::largerSmallerSetter(int leftSize, int rightSize, matrix& leftMatrix, matrix& rightMatrix, matrix*& largermatrix, matrix*& smallerMatrix)
    {
    if(leftSize >= rightSize)
    {
    largermatrix = &leftMatrix;
    smallerMatrix = &rightMatrix;
    }
    else
    {
    largermatrix = &rightMatrix;
    smallerMatrix = &leftMatrix;
    }
    }
    

我对你的问题的评论:

我在一个类中有一个成员函数,它进行比较,然后更改指针指向的内容:

若要更改任何对象的值,您需要将其作为引用传递或将其作为指针传递。在您的情况下,您需要更改指针的值,然后您需要传递pointer as reference或传递指针的地址。否则,您的函数将更改指针的本地副本。

这会产生一个错误。这是由于largerSize和smallerSize居住在0x0地址。

这是因为在函数中,您试图将一个矩阵复制到指针所指向的矩阵(largermatrixsmallerMatrix)。但是,它们并不指向任何有效的对象。您需要使用new来动态分配对象或将预先分配的矩阵的地址传递到其他地方。

最新更新