I am wondering about this because of scope issues. For example, consider the code
typedef struct {
int x1;/*top*/
int x2;/*bottom*/
int id;
} sub
Yes, for a function declared to return a struct
, return
of such a struct will copy it (though the compiler is empowered to optimize the copy away, essentially in cases where it can prove the optimization is semantically innocuous, you can reason "as if" the copying was guaranteed).
However, since you did tag this as C++, not C, why not supply your struct
with a constructor, instead...? Seems clearer and more direct...!-)
Yes, in that case there will be a copy made. If you change the function declaration like this:
subline_t &subline(int x1, int x2, int id) {
then no copy will be made. However, in your specific case it would not be valid to return a reference to an object allocated on the stack. The problem is that the object would be destructed and invalidated before the caller had a chance to use it.
This is related to the common Return Value Optimization for C++ that can avoid doing an actual copy operation in the case you have described. The end result is (or should be) the same as if a copy were done, but you should be aware of the optimization. The presence of this optimization can, in some cases, change the observable behaviour of the program.
The returned class or struct may or may not be copied, depending if the compiler uses copy elision. See the answers to What are copy elision and return value optimization? In short, whether it is copied or not depends on a number of things.
You can of course avoid a copy by returning a reference. In the case of your example, returning a reference is invalid (though the compiler will allow it) because the local struct is allocated on the stack, and therefor the returned reference refers to a deallocated object. However, if the object was passed to your function (directly or as a member of an object) you can safely return a reference to it and avoid copy-on-return.
Finally, if you cannot trust copy elision and you want to avoid copies, you can use and return a unique_ptr
instead of a reference. The object itself will not be copied, although the unique_ptr
itself may or may not be (again, depending on copy elision!). Copying/moving a unique_ptr
is however very cheap if copy elision of the unique_ptr
does not happen for some reason.
Here is an example using unique_ptr
:
#include <memory>
struct A {
public:
int x;
int y;
A(int x, int y) : x(x), y(y) {
}
};
std::unique_ptr<A> returnsA() {
return std::make_unique<A>(3, 4);
}
int main() {
auto a = returnsA();
}
Note that you must (unfortunately) declare a constructor for your struct, or else make_unique
will not compile due to inadequacies of C++.
In your case , it will return a copy
If your code was
subline_t& subline(int, int)
then it would return a reference, which would yield in undefined behaviour.
Just FYI, since in this case you are using only a struct(ure), it is the same behavior as in C language.
Though this is a language feature, it is recommended that it shall not be used