在 C++ 中通过引用传递类成员函数返回值
我一直在寻找解决这个问题的方法,但似乎找不到。我确信这个一般性问题之前已经在某个地方被问过,但希望你能帮助解决我的具体情况...
我有一个类模板 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
?
非常感谢...
I've been searching for a solution to this problem but can't seem to find one. I'm sure this general question has been asked before somewhere but hopefully you can help with my specific situation...
I have a class template someClass
that contain the following (private) members:
int size_x;
int size_y;
int size_total;
T * grid;
someClass
contains a constructor that looks like this:
someClass (const int x, const int y)
: size_x (x), size_y (y), size_total (x*y)
{
grid = new T [size_total];
}
a copy constructor that looks like this:
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));
}
a member function that looks like this:
T * retGrid (void) const
{
return grid;
}
and an assignment operator that looks like this:
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;
}
I'm trying to pass the following two someClass
objects
someClass<double> *I1 = new someClass<double>(10,10);
someClass<double> I2 = *I1;
to a function outside of the someClass
class with the following prototype:
int someFunction(double *arr);
This call works fine:
int status;
status = someFunction(I1->retGrid()); // Properly working function call
but this does not
status = someFunction(&I2.retGrid()); // Compiler gives error that says "error: invalid lvalue in unary &"
And if I call someFunction
like this:
status = someFunction(I2.retGrid()); // Compiler gives no error but function returns error value in status
the code compiles but I get a run-time error (a bad status value from another function call within someFunction
).
How can I properly pass I2
to someFunction
?
Many thanks...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您正在尝试获取 retGrid 返回的临时对象的地址(在本例中是一个指针,但这并不重要)。因此您不能使用
&
方法。如果没有&符号,您会将内部数组从
I2
传递到someFunction
。如果这对您来说不好(即因为您收到某种运行时错误),请考虑复制该数组并将其传递给someFunction
。You are trying to take address of the temporary object (in this case, a pointer but this doesn't really matter) returned by
retGrid
. Hence you cannot use the&
approach.Without the ampersand, you would pass the internal array from
I2
tosomeFunction
. If that's not fine for you (i.e. since you get some kind of runtime error), consider making a copy of this array and passing it tosomeFunction
instead.当类中有指针并且必须为每个对象分配内存时,您需要定义复制构造函数和赋值运算符。您只添加了后者。该初始化
实际上是使用复制构造函数执行的,而不是使用赋值运算符。它与 相同
但是,这是错误的,因为您只为网格分配内存。但是如果网格已经被分配(从之前的分配中),你就会泄漏内存。所以它应该看起来像这样:
When you have pointers in your class and you have to allocate memory for each object, you need to define a copy constructor and an assignment operator. You only added the later. This initialization
is actually performed with a copy constructor, not with the assignment operator. It is identical to
However, it is wrong, because you only allocate memory for grid. But if grid was already allocated (from a previous assignment) you'd leak memory. So it should look like this:
第一个问题:为什么不使用
std::vector
,而不是尝试自己管理内存。你不显示
析构函数;我想你释放了那里的内存。但有
仍然存在问题:
在复制构造函数中,您使用
memcpy
。这不是问题当您实例化
double
时,但这可能是一个问题对于其他类型。您应该使用
std::copy
。如果您使用的是
std::vector
,并且仍需要retGrid
返回一个
T*
,它将是return &grid[0];
。赋值运算符已损坏。它泄露了任何以前的
内存,如果
new
失败,它会将对象留在不一致的状态。 (必须检查自分配是
通常是出现问题的提示。)正确的分配
操作员将在更改之前执行所有可能失败的操作
对象中的任何东西。您可能会搜索有关的信息
交换习惯用法,但类似下面的内容也可以
工作:
。
如果
size_total
相等,您可能需要对此进行优化(或
size_total <= other.size_total
)。当然,如果您使用 std::vector ,编译器会生成
赋值运算符和复制构造函数就足够了;你
不必写任何东西。
您对
I1
使用指针有什么原因吗? (或者是这只是一个更大背景下的产物,你可以从中
提取了代码?)
关于
someFunction( &I2.retGrid() );
,someClass::retGrid()
返回一个指针。无论是否您通过指针或对象调用该函数。服用
地址结果为
T**
。关于最后一次调用,没有什么会导致
您向我们展示的代码中存在问题。只要
I2
是在范围内并且没有删除它的对象,不应该有
问题。这是调用函数的正确方法
目的。您的代码中的问题在其他地方。
First question: why aren't use using
std::vector
, instead oftrying to manage the memory yourself. You don't show the
destructor; I presume you free the memory there. But there are
still problems:
In the copy constructor, you use
memcpy
. That's not a problemwhen you instantiate over
double
, but it could be a problemfor other types. You should be using
std::copy
.If you were using
std::vector
, andretGrid
still needed toreturn a
T*
, it would bereturn &grid[0];
.The assignment operator is broken. It leaks any previous
memory, and if the
new
fails, it leaves the object in aninconsistent state. (Having to check for self-assignment is
usually a hint that something is wrong.) A correct assignment
operator will do all operations which might fail before changing
anything in the object. You might search for information about
the swap idiom, but something like the following would also
work:
.
You might want to optimize this if the
size_total
are equal(or
size_total <= other.size_total
).And of course, if you use
std::vector
, the compiler generatedassignment operator and copy constructor are sufficient; you
don't have to write anything.
Is there any reason why you use a pointer for
I1
? (Or isthis just an artifact of a larger context from which you
extracted the code?)
Concerning
someFunction( &I2.retGrid() );
,someClass::retGrid()
returns a pointer. Regardless of whetheryou call the function through a pointer or an object. Taking
the address results in a
T**
.Concerning the last call, there is nothing that would cause
a problem here in the code you've shown us. As long as
I2
isin scope and hasn't deleted it's object, there should be no
problem. This is the correct way of calling the function on an
object. The problem in your code is elsewhere.
我不确定您收到的运行时错误,但
status = someFunction(&I2.retGrid());
正在将指针传递给临时对象。运行时错误可能是由于缺少在 someClass中调用的复制构造函数所致。 I2 = *I1;
I'm not sure of the runtime error that you are getting but
status = someFunction(&I2.retGrid());
is passing pointer to a temporary object.The runtime error could be because of missing copy constructor that is invoked in
someClass<double> I2 = *I1;
感谢大家提出的非常有用的评论,特别是 AAT、David Rodriguez - drbeas、James Kanze 和 Marius Bancila 的评论。
事实证明,问题出在
someFunction
内与第三方函数的接口不正确。我在睡眠后发现并修复了错误,现在调用:工作正常。
但这次讨论揭示了其他非常重要的相关问题,即与我的复制构造函数和赋值运算符相关的内存管理问题以及建议使用向量。我相信这篇文章在这些优点上有很大的价值。
Thank you to everyone for the extremely useful comments, especially those by AAT, David Rodriguez - dribeas, James Kanze, and Marius Bancila.
It turns out the problem was improper interface with a third-party function inside
someFunction
. I found and fixed the error after some sleep and now the call:works correctly.
But this discussion brought other very important related issues to light, namely the memory management issues related to my copy constructor and assignment operator and suggested use of vectors. I believe this thread has a lot of value on those merits.