Путается с типом возврата (ссылка, константа)

Я ошибочно закончил писать следующий код. Он работает на Windows (с использованием VS2010), но не на Mac (GCC).

Может кто-то описать, что именно происходит в этом случае, и почему он не работает в сборке Mac Release.

const Mystruct* const & GetMyObject() const
{
 return m_pObject;
}

m_pObject - это указатель в этом классе, выделенный в куче.

Отредактировано: над кодом компилируется на Mac. Но когда я выполняю следующий оператор, он дает мне указатель на мусор

Mystruct* pObjectTemp = const_cast<mystruct*>(GetMyObject());
</mystruct*>
4 ответа

Это постоянная ссылка на указатель на постоянный Mystruct.


Вы возвращаете постоянную ссылку на константный указатель, а затем используете 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;
}

Там нет никакой реальной пользы для возвращения указателя по ссылке в данном случае и изменение это поможет предотвратить проблему Майк упоминает здесь.


Может кто-то описать, что именно происходит на возвращаемом типе здесь

Тип возврата - это ссылка на постоянный указатель на постоянный объект Mystruct.

и почему он не работает в сборке Mac Release.

Вы забыли показать объявление Mystruct, но я 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;
}
</iostream>

Компилятор идентифицирует проблему:

$ 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


VS решил ослабить интерпретацию const и разрешил возвращать переменный указатель. Gcc, будучи более строгим в проверке типов, не сделал этого.

В стороне, код, который работает в gcc, имеет тенденцию работать на VS, но обратное не обязательно так.

licensed under cc by-sa 3.0 with attribution.