我一直在寻找这个问题的解决方案,但似乎找不到。我确信在某个地方之前已经提出了这个一般性问题,但希望你可以帮助解决我的具体情况......
我有一个类模板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
?
非常感谢......
答案 0 :(得分:1)
您正在尝试获取retGrid
返回的临时对象的地址(在这种情况下,指针但这并不重要)。因此,您无法使用&
方法。
如果没有&符号,您可以将内部数组从I2
传递到someFunction
。如果这对您来说不合适(即因为您遇到某种运行时错误),请考虑复制此数组并将其传递给someFunction
。
答案 1 :(得分:1)
如果在类中有指针并且必须为每个对象分配内存,则需要定义复制构造函数和赋值运算符。你刚才添加了。这个初始化
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;
}
答案 2 :(得分:1)
第一个问题:为什么不使用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
是
在范围内并没有删除它的对象,应该没有
问题。这是调用函数的正确方法
宾语。代码中的问题出在其他地方。
答案 3 :(得分:0)
我不确定您收到的运行时错误,但status = someFunction(&I2.retGrid());
正在将指针传递给临时对象。
运行时错误可能是因为缺少在someClass<double> I2 = *I1;
答案 4 :(得分:0)
感谢大家提供的非常有用的评论,尤其是AAT,David Rodriguez - dribeas,James Kanze和Marius Bancila的评论。
事实证明,问题是与someFunction
内的第三方功能的接口不正确。我发现并修复了一些睡眠后的错误,现在是电话:
status = someFunction(I2.retGrid()); // Compiler gives no error but function returns error value in status
正常工作。
但是这个讨论带来了其他非常重要的相关问题,即与我的拷贝构造函数和赋值运算符相关的内存管理问题以及向量的建议用法。我相信这个主题在这些优点上有很多价值。