aybe
aybe

Reputation: 16672

Is this the right way to return a struct in a parameter?

I made the following method in a C++/CLI project:

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

    // ...

    data = state;
}

Then I use it like this in another method:

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

It does work, returned data is not garbage, however there's something I don't understand.

Question:

C++ is supposed to clean up state when it has exitted its scope, so data is a copy of state, correct ?

And in what exactly it is different from the following you see on many examples:

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

Which one makes more sense to use or is the right way ?

Reference:

CDROM_TOC_SESSION_DATA

Upvotes: 0

Views: 68

Answers (2)

John Bollinger
John Bollinger

Reputation: 180418

C++ is supposed to clean up state when it has exitted its scope, so data is a copy of state, correct ?

In the first example, the statement

data = state

presumably copies the value of state into local variable data, which is a reference to the same object that is identified by data in the caller's scope (because those are the chosen names -- they don't have to match). I say "presumably" because in principle, an overridden assignment operator could do something else entirely. In any library you would actually want to use, you can assume that the assignment operator does something sensible, but it may be important to know the details, so you should check.

The lifetimes of local variables data and state end when the method exits. They will be cleaned up at that point, and no attempt may be made to access them thereafter. None of that affects the caller's data object.

And in what exactly it is different from the following you see on many examples:

CDROM_TOC_SESSION_DATA data;
GetSessionData(&data);

Not much. Here the caller passes a pointer instead of a reference. GetSessionData must be declared appropriately for that, and its implementation must explicitly dereference the pointer to access the caller's data object, but the general idea is the same for most intents and purposes. Pointer and reference are similar mechanisms for indirect access.

Which one makes more sense to use or is the right way ?

It depends. Passing a reference is generally a bit more idiomatic in C++, and it has the advantage that the method does not have to worry about receiving a null or invalid pointer. On the other hand, passing a pointer is necessary if the function has C linkage, or if you need to accommodate the possibility of receiving a null pointer.

Upvotes: 2

Miles Budnek
Miles Budnek

Reputation: 30569

Using a reference vs a pointer for an out parameter is really more of a matter of style. Both function equally well, but some people feel that the explicit & when calling a function makes it more clear that the function may modify the parameter it was passed.

i.e.

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

Note that 99% of the time the correct way to return a class/struct type is to just return it. i.e.:

MyType getObject()
{
    MyType object{};

    // ...

    return object;
}

Called as

auto obj = getObject();

In the specific case of CDROM_TOC_SESSION_DATA it likely makes sense to use an out parameter, since the class contains a flexible array member. That means that the parameter is almost certainly a reference/pointer to the beginning of some memory buffer that's larger than sizeof(CDROM_TOC_SESSION_DATA), and so must be handled in a somewhat peculiar way.

Upvotes: 2

Related Questions