Это правильный способ вернуть структуру в параметре? - PullRequest
0 голосов
/ 19 марта 2020

Я сделал следующий метод в проекте C ++ / CLI:

void GetSessionData(CDROM_TOC_SESSION_DATA& data)
{
    auto state = CDROM_TOC_SESSION_DATA{};

    // ...

    data = state;
}

Затем я использую его следующим образом:

CDROM_TOC_SESSION_DATA data;
GetSessionData(data);
// do something with data

Он работает, возвращается data это не мусор, но есть кое-что, чего я не понимаю.

Вопрос:

C ++ должен очистить state после выхода из области видимости, data является копией state, верно?

И чем именно это отличается от следующего, что вы видите на многих примерах:

CDROM_TOC_SESSION_DATA data;
GetSessionData(&data); // signature should be GetSession(CDROM_TOC_SESSION_DATA *data)

Какой из них имеет больше смысла использовать или это правильный путь?

Ссылка:

CDROM_TOC_SESSION_DATA

Ответы [ 2 ]

2 голосов
/ 19 марта 2020

C ++ должен очищать состояние после выхода из своей области, поэтому данные являются копией состояния, верно?

В первом примере оператор

data = state

предположительно копирует значение state в локальную переменную data, которая является ссылкой на тот же объект, который обозначен data в области действия вызывающего абонента (потому что это выбранные имена - они не 't имеет для соответствия). Я говорю «предположительно», потому что в принципе переопределенный оператор присваивания может делать что-то еще полностью. В любой библиотеке, которую вы действительно хотите использовать, вы можете предположить, что оператор присваивания делает что-то разумное, но может быть важно знать детали, поэтому вам следует проверить.

Время жизни локальных переменных data и state заканчивается при выходе из метода. В этот момент они будут очищены, и после этого не может быть предпринято никаких попыток получить к ним доступ. Ничто из этого не влияет на объект data вызывающего абонента.

И чем он отличается от того, что вы видите на многих примерах:

CDROM_TOC_SESSION_DATA data;
GetSessionData(&data);

Не так много , Здесь вызывающая сторона передает указатель вместо ссылки. GetSessionData должен быть объявлен соответствующим образом для этого, и его реализация должна явно разыменовать указатель для доступа к объекту data вызывающего, но общая идея для большинства намерений и целей одна и та же. Указатель и ссылка являются аналогичными механизмами для косвенного доступа.

Какой из них имеет больше смысла в использовании или является правильным способом?

Это зависит. Передача ссылки, как правило, немного более идиоматична c в C ++, и она имеет то преимущество, что метод не должен беспокоиться о получении нулевого или недействительного указателя. С другой стороны, передача указателя необходима, если функция имеет связь C или если вам необходимо учесть возможность получения нулевого указателя.

2 голосов
/ 19 марта 2020

Использование ссылки против указателя для параметра out - это скорее вопрос стиля. Оба функционируют одинаково хорошо, но некоторые люди чувствуют, что явный & при вызове функции делает более ясным, что функция может изменить параметр, который был передан.

т.е.

doAThing(someObject);
// It's not clear that doAThing accepts a reference and
// therefore may modify someObject

vs

doAThing(&someObject);
// It's clear that doAThing accepts a pointer and it's
// therefore possible for it to modify someOjbect

Обратите внимание, что в 99% случаев правильный способ вернуть тип класса / структуры - просто return. т.е.:

MyType getObject()
{
    MyType object{};

    // ...

    return object;
}

Вызывается как

auto obj = getObject();

В конкретном c случае CDROM_TOC_SESSION_DATA, вероятно, имеет смысл использовать параметр out, поскольку класс содержит член гибкого массива. Это означает, что параметр почти наверняка является ссылкой / указателем на начало некоторого буфера памяти, который больше sizeof(CDROM_TOC_SESSION_DATA), и поэтому должен обрабатываться несколько особым образом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...