与返回类型(引用、常量引用)混淆



我错误地编写了以下代码。它适用于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上运行,但情况不一定相反。

最新更新