我错误地编写了以下代码。它适用于Windows(使用VS2010),但不适用于Mac(GCC)。
有人能描述一下这里的返回类型到底发生了什么,以及为什么它在Mac Release版本中不起作用吗。
const Mystruct* const & GetMyObject() const
{
return m_pObject;
}
m_pObject是此类中在堆上分配的指针。
编辑时间:以上代码在Mac上编译。但当我执行以下语句时,它会给我一个垃圾指针
Mystruct* pObjectTemp = const_cast<Mystruct*>(GetMyObject());
它是指向常量Mystruct的指针的常量引用。
有人能描述一下这里的退货类型到底发生了什么吗
返回类型是对指向常量Mystruct
对象的常量指针的引用。
以及为什么它不适用于Mac Release版本。
您忘记显示Mystruct
的声明,但我猜它是一个声明为:的成员
Mystruct* m_pObject;
请注意,没有const
,使其成为函数返回引用的const Mystruct*
的不同指针类型。
在这种情况下,您试图返回对错误指针类型的引用:const Mystruct*
而不是Mystruct*
。为了返回正确的类型,函数必须创建一个类型为const Mystruct*
的临时指针。然而,在返回对临时的引用后,它超出了作用域,可能会被垃圾覆盖:使用返回值会产生未定义的行为。
要修复它,请按值返回指针:
const Mystruct* GetMyObject() const {return m_pObject;}
你可能还想要一个非恒定的过载,以避免不可靠的铸造:
Mystruct* GetMyObject() {return m_pObject;}
更新:
为了证明这确实是问题所在(假设我猜测m_pObject
的类型是正确的),请考虑以下内容:
#include <iostream>
struct Mystruct {};
struct Test {
Test() : m_pObject(0) {}
const Mystruct * const & GetMyObject() const {
return m_pObject;
}
Mystruct * m_pObject;
};
int main() {
Test test;
std::cout << "MEMBER: " << &test.m_pObject << std::endl;
std::cout << "RETURN: " << &test.GetMyObject() << std::endl;
}
编译器识别问题:
$ g++ test.cpp
test.cpp: In member function ‘const Mystruct* const& Test::GetMyObject() const’:
test.cpp:9:16: warning: returning reference to temporary [enabled by default]
并且运行它表明返回的引用不而引用成员:
$ ./a.out
MEMBER: 0x7fff7a3c4c20
RETURN: 0x7fff7a3c4c08
返回对常量指针的常量引用,然后使用const_cast
将其转换为原始指针。这种转换不起作用:http://en.cppreference.com/w/cpp/language/const_cast
const Mystruct* pObjectTemp = t.GetMyObject();
它应该返回与实例化的t
对象中的指针相同的指针(请注意,如果t在堆栈上,一旦它超出范围,析构函数就应该清理它的内存,这意味着pObjectTemp将指向不再分配的内存)。
您还应该修改您的功能:
const Mystruct* const GetMyObject() const
{
return m_pObject;
}
在这种情况下,通过引用返回指针并没有真正的好处,而更改它将防止Mike在这里提到的问题。
VS决定放宽对const的解释,并允许返回一个变量指针。Gcc在类型检查方面更严格,但没有。
顺便说一句,在gcc中运行的代码往往在VS上运行,但情况不一定相反。