通过引用传递类成员函数返回值C++

Passing class member function return value by reference in C++

本文关键字:成员 函数 返回值 C++ 引用      更新时间:2023-10-16

我一直在寻找解决这个问题的方法,但似乎找不到。我相信这个一般性问题之前已经在某个地方问过,但希望你能帮助解决我的具体情况......

我有一个包含以下(私有)成员的类模板someClass

int     size_x;
int     size_y;
int     size_total;
T *     grid;

someClass包含一个如下所示的构造函数:

someClass (const int x, const int y)
: size_x (x), size_y (y), size_total (x*y)
{
    grid = new T [size_total];
}

如下所示的复制构造函数:

someClass (const someClass & rhs)
{
    size_x = rhs.size_x;
    size_y = rhs.size_y;
    size_total = rhs.size_total;
    grid = new T [size_total];
    memcpy(grid, rhs.grid, size_total*sizeof(T));
}

如下所示的成员函数:

T * retGrid (void) const
{
    return grid;
}

以及如下所示的赋值运算符:

someClass & operator= (const someClass & rhs)
{
    if (this != &rhs)
    {
        size_x = rhs.size_x;
        size_y = rhs.size_y;
        size_total = rhs.size_total;
        grid = new T [size_total];
        memcpy(grid, rhs.grid, size_total*sizeof(T));
    }
    return *this;
}

我正在尝试传递以下两个someClass对象

someClass<double> *I1 = new someClass<double>(10,10);
someClass<double> I2 = *I1;

到具有以下原型的 someClass 类之外的函数:

int someFunction(double *arr);

此调用工作正常:

int status;
status = someFunction(I1->retGrid()); // Properly working function call

但这并没有

status = someFunction(&I2.retGrid()); // Compiler gives error that says "error: invalid lvalue in unary &"

如果我这样称呼someFunction

status = someFunction(I2.retGrid()); // Compiler gives no error but function returns error value in status

代码编译,但我收到运行时错误(someFunction内另一个函数调用的状态值错误)。

如何正确地将I2传递给someFunction

非常感谢...

您正在尝试获取retGrid返回的临时对象的地址(在本例中为指针,但这并不重要)。因此,您不能使用&方法。

如果没有 & 符号,您将内部数组从 I2 传递到 someFunction 。如果这对您来说不合适(即因为您遇到某种运行时错误),请考虑复制此数组并将其传递给someFunction

当您的类中有指针并且必须为每个对象分配内存时,您需要定义复制构造函数和赋值运算符。您只添加了后者。此初始化

someClass<double> I2 = *I1;

实际上是使用复制构造函数执行的,而不是使用赋值运算符执行的。它与

someClass<double> I2(*I1);

但是,这是错误的,因为您只为网格分配内存。但是,如果网格已经分配(来自以前的分配),则会泄漏内存。所以它应该看起来像这样:

someClass & operator= (const someClass & rhs)
{
    if (this != &rhs)
    {
        size_x = rhs.size_x;
        size_y = rhs.size_y;
        size_total = rhs.size_total;
        delete [] grid;
        grid = new T [size_total];
        memcpy(grid, rhs.grid, size_total*sizeof(T));
    }
    return *this;
}

第一个问题:为什么不使用 std::vector 而不是尝试自己管理内存。 您不显示破坏者;我想你释放了那里的记忆。 但是有仍然有问题:

  • 在复制构造函数中,使用 memcpy 。 这不是问题当您实例化double 时,但这可能是一个问题对于其他类型。 您应该使用 std::copy .

  • 如果您使用的是 std::vector ,并且retGrid仍然需要返回一个T*,它将是return &grid[0];

  • 赋值运算符已损坏。 它泄漏了任何以前的内存,如果new失败,它将对象留在状态不一致。 (必须检查自我分配是通常是暗示出了问题。 正确的分配运算符将在更改之前执行所有可能失败的操作对象中的任何内容。 您可以搜索有关交换成语,但类似以下内容的内容也会工作:

.

SomeClass&
SomeClass<T>::operator=( SomeClass const& other )
{
    T* newGrid = new T[other.size_total];
    std::copy( other.grid, other.grid + other.size_total, newGrid );
    delete [] grid;
    size_x = other.size_x;
    size_y = other.size_y;
    size_total = other.size_total;
    grid = newGrid;
    return *this;
}

如果size_total相等,则可能需要对此进行优化(或size_total <= other.size_total)。

当然,如果你使用std::vector,编译器生成赋值运算符和复制构造函数就足够了;你不必写任何东西。

  • 有什么理由使用指针进行I1吗? (或者这只是一个更大背景的工件,你从中提取代码?

  • 关于someFunction( &I2.retGrid() );someClass::retGrid()返回一个指针。 无论是否通过指针或对象调用函数。 服用该地址会导致T**

  • 关于最后一个电话,没有什么会导致您向我们展示的代码中存在问题。 只要I2在范围内并且没有删除它的对象,应该没有问题。 这是在对象。 代码中的问题出在其他地方。

我不确定您收到的运行时错误status = someFunction(&I2.retGrid());但正在传递指向临时对象的指针。

运行时错误可能是因为缺少在 someClass<double> I2 = *I1; 中调用的复制构造函数

感谢大家的非常有用的评论,特别是AAT,David Rodriguez - dribeas,James Kanze和Marius Bancila的评论。

事实证明,问题是与someFunction内部第三方功能的接口不正确。我在睡眠后发现并修复了错误,现在打电话:

status = someFunction(I2.retGrid()); // Compiler gives no error but function returns error value in status

工作正常。

但是这个讨论揭示了其他非常重要的相关问题,即与我的复制构造函数和赋值运算符相关的内存管理问题,以及建议使用向量。我相信这个线程在这些优点上有很大的价值。