Does it make sense for a function to return an rvalue reference?Is returning by rvalue reference more efficient?What should main() return in C and C++?Advantages of using forwardClasses, Rvalues and Rvalue ReferencesImage Processing: Algorithm Improvement for 'Coca-Cola Can' RecognitionWhy should I use a pointer rather than the object itself?Does this rvalue signature pattern make sense?Replacing a 32-bit loop counter with 64-bit introduces crazy performance deviationsReturn value or rvalue reference?Rvalue and Lvalue Referencesrvalue reference or forwarding reference?
Is throwing dice a stochastic or a deterministic process?
How to speed up large double sums in a table?
My dual citizen son (US and Australia) wants to marry a US citizen but live in Australia
Which "exotic salt" can lower water's freezing point by –70 °C?
How did the Apollo guidance computer handle parity bit errors?
Summer '19 Sandbox error: String index out of range: 0: Source
Lines too long in piece with two sections for different instruments
How long did it take Captain Marvel to travel to Earth?
What does the coin flipping before dying mean?
Changing stroke width vertically but not horizontally in Inkscape
Game artist computer workstation set-up – is this overkill?
How do I, as a DM, handle a party that decides to set up an ambush in a dungeon?
Which version of the Squat Nimbleness feat is correct?
Emergency stop in plain TeX, pdfTeX, XeTeX and LuaTeX?
What does the copyright in a dissertation protect exactly?
Transistor gain, what if there is not enough current?
Installing Debian 10, upgrade to stable later?
Can I combine SELECT TOP() with the IN operator?
When referring to a person only by their surname, should I keep or omit "von"?
Why increasing of the temperature of the objects like wood, paper etc. doesn't fire them?
In "Avengers: Endgame", what does this name refer to?
Reverse ColorFunction or ColorData
Why can’t you see at the start of the Big Bang?
Dimmer switch not connected to ground
Does it make sense for a function to return an rvalue reference?
Is returning by rvalue reference more efficient?What should main() return in C and C++?Advantages of using forwardClasses, Rvalues and Rvalue ReferencesImage Processing: Algorithm Improvement for 'Coca-Cola Can' RecognitionWhy should I use a pointer rather than the object itself?Does this rvalue signature pattern make sense?Replacing a 32-bit loop counter with 64-bit introduces crazy performance deviationsReturn value or rvalue reference?Rvalue and Lvalue Referencesrvalue reference or forwarding reference?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;
What would be a valid use case for a signature like this?:
T&& foo();
Or is the rvalue ref only intended for use as argument?
How would one use a function like this?
T&& t = foo(); // is this a thing? And when would t get destructed?
c++
add a comment |
What would be a valid use case for a signature like this?:
T&& foo();
Or is the rvalue ref only intended for use as argument?
How would one use a function like this?
T&& t = foo(); // is this a thing? And when would t get destructed?
c++
6
std::move
comes to mind. It certainly returnsT&&
. Edit :std::optional::value
also has anT&&
overload. Edit 2 : It also has aconst T &&
overload, though I'll admit I don't understand the meaning.
– François Andrieux
May 2 at 19:32
1
@FrançoisAndrieux thestd::get
family of functions, too.
– Brian
May 2 at 19:34
1
See this answer.
– lubgr
May 2 at 19:37
Isn't that a forwarding reference?
– user2357112
May 3 at 1:52
add a comment |
What would be a valid use case for a signature like this?:
T&& foo();
Or is the rvalue ref only intended for use as argument?
How would one use a function like this?
T&& t = foo(); // is this a thing? And when would t get destructed?
c++
What would be a valid use case for a signature like this?:
T&& foo();
Or is the rvalue ref only intended for use as argument?
How would one use a function like this?
T&& t = foo(); // is this a thing? And when would t get destructed?
c++
c++
edited May 3 at 2:35
Boann
37.7k1291123
37.7k1291123
asked May 2 at 19:22
Martin B.Martin B.
842314
842314
6
std::move
comes to mind. It certainly returnsT&&
. Edit :std::optional::value
also has anT&&
overload. Edit 2 : It also has aconst T &&
overload, though I'll admit I don't understand the meaning.
– François Andrieux
May 2 at 19:32
1
@FrançoisAndrieux thestd::get
family of functions, too.
– Brian
May 2 at 19:34
1
See this answer.
– lubgr
May 2 at 19:37
Isn't that a forwarding reference?
– user2357112
May 3 at 1:52
add a comment |
6
std::move
comes to mind. It certainly returnsT&&
. Edit :std::optional::value
also has anT&&
overload. Edit 2 : It also has aconst T &&
overload, though I'll admit I don't understand the meaning.
– François Andrieux
May 2 at 19:32
1
@FrançoisAndrieux thestd::get
family of functions, too.
– Brian
May 2 at 19:34
1
See this answer.
– lubgr
May 2 at 19:37
Isn't that a forwarding reference?
– user2357112
May 3 at 1:52
6
6
std::move
comes to mind. It certainly returns T&&
. Edit : std::optional::value
also has an T&&
overload. Edit 2 : It also has a const T &&
overload, though I'll admit I don't understand the meaning.– François Andrieux
May 2 at 19:32
std::move
comes to mind. It certainly returns T&&
. Edit : std::optional::value
also has an T&&
overload. Edit 2 : It also has a const T &&
overload, though I'll admit I don't understand the meaning.– François Andrieux
May 2 at 19:32
1
1
@FrançoisAndrieux the
std::get
family of functions, too.– Brian
May 2 at 19:34
@FrançoisAndrieux the
std::get
family of functions, too.– Brian
May 2 at 19:34
1
1
See this answer.
– lubgr
May 2 at 19:37
See this answer.
– lubgr
May 2 at 19:37
Isn't that a forwarding reference?
– user2357112
May 3 at 1:52
Isn't that a forwarding reference?
– user2357112
May 3 at 1:52
add a comment |
3 Answers
3
active
oldest
votes
For a free function it doesn't make much sense to return a rvalue reference. If it is a non-static local object then you never want to return a reference or pointer to it because it will be destroyed after the function returns. It can possibly make sense to return a rvalue reference to an object that you passed to the function though. It really depends on the use case for if it makes sense or not.
One thing that can greatly benefit from returning an rvalue reference is a member function of a temporary object. Lets say you have
class foo
std::vector<int> bar
public:
foo(int n) : bar(n)
std::vector<int>& get_vec() return bar;
;
If you do
auto vec = foo(10).get_vec();
you have to copy because get_vec
returns an lvalue. If you instead use
class foo
std::vector<int> bar
public:
foo(int n) : bar(n)
std::vector<int>& get_vec() & return bar;
std::vector<int>&& get_vec() && return std::move(bar);
;
Then vec
would be able to move the vector returned by get_vec
and you save yourself an expensive copy operation.
@FrançoisAndrieux That's covered by my It can possibly make sense to return a rvalue reference to an object that you passed to the function though. It really depends on the use case for if it makes sense or not. catch all. I know there are cases but I really didn't want to try and list them all.
– NathanOliver
May 2 at 19:37
Is there a reason to prefer returning by rvalue-ref compared to returning by value here?
– super
May 2 at 19:38
@super I take it your talking about theget_vec
case? If you return by value you incur 2 move operations. Passing by rvalue reference you only have 1 move.
– NathanOliver
May 2 at 19:39
1
@NathanOliver Well, you can call it on any rvalue (e.g.std::move(a).get_vec()
). My point is that you're potentially returning a reference to an object that's about to be destroyed. It's the same problem as returning a reference to a local function variable.
– Cruz Jean
May 2 at 20:03
2
std::vector<int> get_vec() && return std::move(bar);
in this case ends up being better 999/1000. Can you come up with a better example?
– Yakk - Adam Nevraumont
May 2 at 20:08
|
show 2 more comments
T&& t = foo(); // is this a thing? And when would t get destructed?
An rvalue reference is really similar to a lvalue reference. Think about your example like it was normal references:
T& foo();
T& t = foo(); // when is t destroyed?
The answer is that t
is still valid to use as long as the object is refers to lives.
The same answer still applies to you rvalue reference example.
But... does it make sense to return an rvalue reference?
Sometimes, yes. But very rarely.
consider this:
std::vector<int> v = ...;
// type is std::tuple<std::vector<int>&&>
auto parameters = std::forward_as_tuple(std::move(v));
// fwd is a rvalue reference since std::get returns one.
// fwd is valid as long as v is.
decltype(auto) fwd = std::get<0>(parameters);
// useful for calling function in generic context without copying
consume(std::get<0>(parameters));
So yes there are example. Here, another interesting one:
struct wrapper
auto operator*() & -> Heavy&
return heavy;
auto operator*() && -> Heavy&&
return std::move(heavy);
private:
Heavy instance;
;
// by value
void use_heavy(Heavy);
// since the wrapper is a temporary, the
// Heavy contained will be a temporary too.
use_heavy(*make_wrapper());
In the last example, if thewrapper
instance you use this on is a temporary,operator*()
returns a reference toinstance
, which is likewise a temporary. So after the function returns you have a reference to an object whose lifetime has ended (undefined behavior).
– Cruz Jean
May 2 at 20:51
@CruzJean corrected
– Guillaume Racicot
May 2 at 20:57
add a comment |
I think a use case would be to explicitly give permission to "empty" some non-local variable. Perhaps something like this:
class Logger
public:
void log(const char* msg)
logs.append(msg);
std::vector<std::string>&& dumpLogs()
return std::move(logs);
private:
std::vector<std::string> logs;
;
But I admit I made this up now, I never actually used it and it also can be done like this:
std::vector<std::string> dumpLogs()
auto dumped_logs = logs;
return dumped_logs;
That's what the other answers have come up with as well, but in the case where this is called on a temporary object, by the time the function returns you have an (rvalue) reference to an object whose lifetime has ended (undefined behavior).
– Cruz Jean
May 2 at 20:52
@CruzJean Well, my answer was here first and no one downvoted/complained yet so I will keep it here. I am not returning any reference to a temporary anywhere.
– Quimby
May 2 at 20:58
return std::move(logs);
where the return value is a reference type and*this
is a temporary (due to being an rvalue method) makesthis->logs
a temporary as well. That's the reference to a temporary I mean.
– Cruz Jean
May 2 at 22:25
@CruzJean Do you mean e.g.auto&& x = Logger.dumpLogs();
? Yes, that is dangling reference, but that happens for all getters no matter what type of reference they return. My use case would be something likeLogger l; /*calls to log()*/, auto logs = l.dumpLogs();/*log again.. and repeat.*/
– Quimby
2 days ago
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55958970%2fdoes-it-make-sense-for-a-function-to-return-an-rvalue-reference%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
For a free function it doesn't make much sense to return a rvalue reference. If it is a non-static local object then you never want to return a reference or pointer to it because it will be destroyed after the function returns. It can possibly make sense to return a rvalue reference to an object that you passed to the function though. It really depends on the use case for if it makes sense or not.
One thing that can greatly benefit from returning an rvalue reference is a member function of a temporary object. Lets say you have
class foo
std::vector<int> bar
public:
foo(int n) : bar(n)
std::vector<int>& get_vec() return bar;
;
If you do
auto vec = foo(10).get_vec();
you have to copy because get_vec
returns an lvalue. If you instead use
class foo
std::vector<int> bar
public:
foo(int n) : bar(n)
std::vector<int>& get_vec() & return bar;
std::vector<int>&& get_vec() && return std::move(bar);
;
Then vec
would be able to move the vector returned by get_vec
and you save yourself an expensive copy operation.
@FrançoisAndrieux That's covered by my It can possibly make sense to return a rvalue reference to an object that you passed to the function though. It really depends on the use case for if it makes sense or not. catch all. I know there are cases but I really didn't want to try and list them all.
– NathanOliver
May 2 at 19:37
Is there a reason to prefer returning by rvalue-ref compared to returning by value here?
– super
May 2 at 19:38
@super I take it your talking about theget_vec
case? If you return by value you incur 2 move operations. Passing by rvalue reference you only have 1 move.
– NathanOliver
May 2 at 19:39
1
@NathanOliver Well, you can call it on any rvalue (e.g.std::move(a).get_vec()
). My point is that you're potentially returning a reference to an object that's about to be destroyed. It's the same problem as returning a reference to a local function variable.
– Cruz Jean
May 2 at 20:03
2
std::vector<int> get_vec() && return std::move(bar);
in this case ends up being better 999/1000. Can you come up with a better example?
– Yakk - Adam Nevraumont
May 2 at 20:08
|
show 2 more comments
For a free function it doesn't make much sense to return a rvalue reference. If it is a non-static local object then you never want to return a reference or pointer to it because it will be destroyed after the function returns. It can possibly make sense to return a rvalue reference to an object that you passed to the function though. It really depends on the use case for if it makes sense or not.
One thing that can greatly benefit from returning an rvalue reference is a member function of a temporary object. Lets say you have
class foo
std::vector<int> bar
public:
foo(int n) : bar(n)
std::vector<int>& get_vec() return bar;
;
If you do
auto vec = foo(10).get_vec();
you have to copy because get_vec
returns an lvalue. If you instead use
class foo
std::vector<int> bar
public:
foo(int n) : bar(n)
std::vector<int>& get_vec() & return bar;
std::vector<int>&& get_vec() && return std::move(bar);
;
Then vec
would be able to move the vector returned by get_vec
and you save yourself an expensive copy operation.
@FrançoisAndrieux That's covered by my It can possibly make sense to return a rvalue reference to an object that you passed to the function though. It really depends on the use case for if it makes sense or not. catch all. I know there are cases but I really didn't want to try and list them all.
– NathanOliver
May 2 at 19:37
Is there a reason to prefer returning by rvalue-ref compared to returning by value here?
– super
May 2 at 19:38
@super I take it your talking about theget_vec
case? If you return by value you incur 2 move operations. Passing by rvalue reference you only have 1 move.
– NathanOliver
May 2 at 19:39
1
@NathanOliver Well, you can call it on any rvalue (e.g.std::move(a).get_vec()
). My point is that you're potentially returning a reference to an object that's about to be destroyed. It's the same problem as returning a reference to a local function variable.
– Cruz Jean
May 2 at 20:03
2
std::vector<int> get_vec() && return std::move(bar);
in this case ends up being better 999/1000. Can you come up with a better example?
– Yakk - Adam Nevraumont
May 2 at 20:08
|
show 2 more comments
For a free function it doesn't make much sense to return a rvalue reference. If it is a non-static local object then you never want to return a reference or pointer to it because it will be destroyed after the function returns. It can possibly make sense to return a rvalue reference to an object that you passed to the function though. It really depends on the use case for if it makes sense or not.
One thing that can greatly benefit from returning an rvalue reference is a member function of a temporary object. Lets say you have
class foo
std::vector<int> bar
public:
foo(int n) : bar(n)
std::vector<int>& get_vec() return bar;
;
If you do
auto vec = foo(10).get_vec();
you have to copy because get_vec
returns an lvalue. If you instead use
class foo
std::vector<int> bar
public:
foo(int n) : bar(n)
std::vector<int>& get_vec() & return bar;
std::vector<int>&& get_vec() && return std::move(bar);
;
Then vec
would be able to move the vector returned by get_vec
and you save yourself an expensive copy operation.
For a free function it doesn't make much sense to return a rvalue reference. If it is a non-static local object then you never want to return a reference or pointer to it because it will be destroyed after the function returns. It can possibly make sense to return a rvalue reference to an object that you passed to the function though. It really depends on the use case for if it makes sense or not.
One thing that can greatly benefit from returning an rvalue reference is a member function of a temporary object. Lets say you have
class foo
std::vector<int> bar
public:
foo(int n) : bar(n)
std::vector<int>& get_vec() return bar;
;
If you do
auto vec = foo(10).get_vec();
you have to copy because get_vec
returns an lvalue. If you instead use
class foo
std::vector<int> bar
public:
foo(int n) : bar(n)
std::vector<int>& get_vec() & return bar;
std::vector<int>&& get_vec() && return std::move(bar);
;
Then vec
would be able to move the vector returned by get_vec
and you save yourself an expensive copy operation.
answered May 2 at 19:34
NathanOliverNathanOliver
101k17141224
101k17141224
@FrançoisAndrieux That's covered by my It can possibly make sense to return a rvalue reference to an object that you passed to the function though. It really depends on the use case for if it makes sense or not. catch all. I know there are cases but I really didn't want to try and list them all.
– NathanOliver
May 2 at 19:37
Is there a reason to prefer returning by rvalue-ref compared to returning by value here?
– super
May 2 at 19:38
@super I take it your talking about theget_vec
case? If you return by value you incur 2 move operations. Passing by rvalue reference you only have 1 move.
– NathanOliver
May 2 at 19:39
1
@NathanOliver Well, you can call it on any rvalue (e.g.std::move(a).get_vec()
). My point is that you're potentially returning a reference to an object that's about to be destroyed. It's the same problem as returning a reference to a local function variable.
– Cruz Jean
May 2 at 20:03
2
std::vector<int> get_vec() && return std::move(bar);
in this case ends up being better 999/1000. Can you come up with a better example?
– Yakk - Adam Nevraumont
May 2 at 20:08
|
show 2 more comments
@FrançoisAndrieux That's covered by my It can possibly make sense to return a rvalue reference to an object that you passed to the function though. It really depends on the use case for if it makes sense or not. catch all. I know there are cases but I really didn't want to try and list them all.
– NathanOliver
May 2 at 19:37
Is there a reason to prefer returning by rvalue-ref compared to returning by value here?
– super
May 2 at 19:38
@super I take it your talking about theget_vec
case? If you return by value you incur 2 move operations. Passing by rvalue reference you only have 1 move.
– NathanOliver
May 2 at 19:39
1
@NathanOliver Well, you can call it on any rvalue (e.g.std::move(a).get_vec()
). My point is that you're potentially returning a reference to an object that's about to be destroyed. It's the same problem as returning a reference to a local function variable.
– Cruz Jean
May 2 at 20:03
2
std::vector<int> get_vec() && return std::move(bar);
in this case ends up being better 999/1000. Can you come up with a better example?
– Yakk - Adam Nevraumont
May 2 at 20:08
@FrançoisAndrieux That's covered by my It can possibly make sense to return a rvalue reference to an object that you passed to the function though. It really depends on the use case for if it makes sense or not. catch all. I know there are cases but I really didn't want to try and list them all.
– NathanOliver
May 2 at 19:37
@FrançoisAndrieux That's covered by my It can possibly make sense to return a rvalue reference to an object that you passed to the function though. It really depends on the use case for if it makes sense or not. catch all. I know there are cases but I really didn't want to try and list them all.
– NathanOliver
May 2 at 19:37
Is there a reason to prefer returning by rvalue-ref compared to returning by value here?
– super
May 2 at 19:38
Is there a reason to prefer returning by rvalue-ref compared to returning by value here?
– super
May 2 at 19:38
@super I take it your talking about the
get_vec
case? If you return by value you incur 2 move operations. Passing by rvalue reference you only have 1 move.– NathanOliver
May 2 at 19:39
@super I take it your talking about the
get_vec
case? If you return by value you incur 2 move operations. Passing by rvalue reference you only have 1 move.– NathanOliver
May 2 at 19:39
1
1
@NathanOliver Well, you can call it on any rvalue (e.g.
std::move(a).get_vec()
). My point is that you're potentially returning a reference to an object that's about to be destroyed. It's the same problem as returning a reference to a local function variable.– Cruz Jean
May 2 at 20:03
@NathanOliver Well, you can call it on any rvalue (e.g.
std::move(a).get_vec()
). My point is that you're potentially returning a reference to an object that's about to be destroyed. It's the same problem as returning a reference to a local function variable.– Cruz Jean
May 2 at 20:03
2
2
std::vector<int> get_vec() && return std::move(bar);
in this case ends up being better 999/1000. Can you come up with a better example?– Yakk - Adam Nevraumont
May 2 at 20:08
std::vector<int> get_vec() && return std::move(bar);
in this case ends up being better 999/1000. Can you come up with a better example?– Yakk - Adam Nevraumont
May 2 at 20:08
|
show 2 more comments
T&& t = foo(); // is this a thing? And when would t get destructed?
An rvalue reference is really similar to a lvalue reference. Think about your example like it was normal references:
T& foo();
T& t = foo(); // when is t destroyed?
The answer is that t
is still valid to use as long as the object is refers to lives.
The same answer still applies to you rvalue reference example.
But... does it make sense to return an rvalue reference?
Sometimes, yes. But very rarely.
consider this:
std::vector<int> v = ...;
// type is std::tuple<std::vector<int>&&>
auto parameters = std::forward_as_tuple(std::move(v));
// fwd is a rvalue reference since std::get returns one.
// fwd is valid as long as v is.
decltype(auto) fwd = std::get<0>(parameters);
// useful for calling function in generic context without copying
consume(std::get<0>(parameters));
So yes there are example. Here, another interesting one:
struct wrapper
auto operator*() & -> Heavy&
return heavy;
auto operator*() && -> Heavy&&
return std::move(heavy);
private:
Heavy instance;
;
// by value
void use_heavy(Heavy);
// since the wrapper is a temporary, the
// Heavy contained will be a temporary too.
use_heavy(*make_wrapper());
In the last example, if thewrapper
instance you use this on is a temporary,operator*()
returns a reference toinstance
, which is likewise a temporary. So after the function returns you have a reference to an object whose lifetime has ended (undefined behavior).
– Cruz Jean
May 2 at 20:51
@CruzJean corrected
– Guillaume Racicot
May 2 at 20:57
add a comment |
T&& t = foo(); // is this a thing? And when would t get destructed?
An rvalue reference is really similar to a lvalue reference. Think about your example like it was normal references:
T& foo();
T& t = foo(); // when is t destroyed?
The answer is that t
is still valid to use as long as the object is refers to lives.
The same answer still applies to you rvalue reference example.
But... does it make sense to return an rvalue reference?
Sometimes, yes. But very rarely.
consider this:
std::vector<int> v = ...;
// type is std::tuple<std::vector<int>&&>
auto parameters = std::forward_as_tuple(std::move(v));
// fwd is a rvalue reference since std::get returns one.
// fwd is valid as long as v is.
decltype(auto) fwd = std::get<0>(parameters);
// useful for calling function in generic context without copying
consume(std::get<0>(parameters));
So yes there are example. Here, another interesting one:
struct wrapper
auto operator*() & -> Heavy&
return heavy;
auto operator*() && -> Heavy&&
return std::move(heavy);
private:
Heavy instance;
;
// by value
void use_heavy(Heavy);
// since the wrapper is a temporary, the
// Heavy contained will be a temporary too.
use_heavy(*make_wrapper());
In the last example, if thewrapper
instance you use this on is a temporary,operator*()
returns a reference toinstance
, which is likewise a temporary. So after the function returns you have a reference to an object whose lifetime has ended (undefined behavior).
– Cruz Jean
May 2 at 20:51
@CruzJean corrected
– Guillaume Racicot
May 2 at 20:57
add a comment |
T&& t = foo(); // is this a thing? And when would t get destructed?
An rvalue reference is really similar to a lvalue reference. Think about your example like it was normal references:
T& foo();
T& t = foo(); // when is t destroyed?
The answer is that t
is still valid to use as long as the object is refers to lives.
The same answer still applies to you rvalue reference example.
But... does it make sense to return an rvalue reference?
Sometimes, yes. But very rarely.
consider this:
std::vector<int> v = ...;
// type is std::tuple<std::vector<int>&&>
auto parameters = std::forward_as_tuple(std::move(v));
// fwd is a rvalue reference since std::get returns one.
// fwd is valid as long as v is.
decltype(auto) fwd = std::get<0>(parameters);
// useful for calling function in generic context without copying
consume(std::get<0>(parameters));
So yes there are example. Here, another interesting one:
struct wrapper
auto operator*() & -> Heavy&
return heavy;
auto operator*() && -> Heavy&&
return std::move(heavy);
private:
Heavy instance;
;
// by value
void use_heavy(Heavy);
// since the wrapper is a temporary, the
// Heavy contained will be a temporary too.
use_heavy(*make_wrapper());
T&& t = foo(); // is this a thing? And when would t get destructed?
An rvalue reference is really similar to a lvalue reference. Think about your example like it was normal references:
T& foo();
T& t = foo(); // when is t destroyed?
The answer is that t
is still valid to use as long as the object is refers to lives.
The same answer still applies to you rvalue reference example.
But... does it make sense to return an rvalue reference?
Sometimes, yes. But very rarely.
consider this:
std::vector<int> v = ...;
// type is std::tuple<std::vector<int>&&>
auto parameters = std::forward_as_tuple(std::move(v));
// fwd is a rvalue reference since std::get returns one.
// fwd is valid as long as v is.
decltype(auto) fwd = std::get<0>(parameters);
// useful for calling function in generic context without copying
consume(std::get<0>(parameters));
So yes there are example. Here, another interesting one:
struct wrapper
auto operator*() & -> Heavy&
return heavy;
auto operator*() && -> Heavy&&
return std::move(heavy);
private:
Heavy instance;
;
// by value
void use_heavy(Heavy);
// since the wrapper is a temporary, the
// Heavy contained will be a temporary too.
use_heavy(*make_wrapper());
edited May 2 at 20:57
answered May 2 at 19:35
Guillaume RacicotGuillaume Racicot
16.9k53874
16.9k53874
In the last example, if thewrapper
instance you use this on is a temporary,operator*()
returns a reference toinstance
, which is likewise a temporary. So after the function returns you have a reference to an object whose lifetime has ended (undefined behavior).
– Cruz Jean
May 2 at 20:51
@CruzJean corrected
– Guillaume Racicot
May 2 at 20:57
add a comment |
In the last example, if thewrapper
instance you use this on is a temporary,operator*()
returns a reference toinstance
, which is likewise a temporary. So after the function returns you have a reference to an object whose lifetime has ended (undefined behavior).
– Cruz Jean
May 2 at 20:51
@CruzJean corrected
– Guillaume Racicot
May 2 at 20:57
In the last example, if the
wrapper
instance you use this on is a temporary, operator*()
returns a reference to instance
, which is likewise a temporary. So after the function returns you have a reference to an object whose lifetime has ended (undefined behavior).– Cruz Jean
May 2 at 20:51
In the last example, if the
wrapper
instance you use this on is a temporary, operator*()
returns a reference to instance
, which is likewise a temporary. So after the function returns you have a reference to an object whose lifetime has ended (undefined behavior).– Cruz Jean
May 2 at 20:51
@CruzJean corrected
– Guillaume Racicot
May 2 at 20:57
@CruzJean corrected
– Guillaume Racicot
May 2 at 20:57
add a comment |
I think a use case would be to explicitly give permission to "empty" some non-local variable. Perhaps something like this:
class Logger
public:
void log(const char* msg)
logs.append(msg);
std::vector<std::string>&& dumpLogs()
return std::move(logs);
private:
std::vector<std::string> logs;
;
But I admit I made this up now, I never actually used it and it also can be done like this:
std::vector<std::string> dumpLogs()
auto dumped_logs = logs;
return dumped_logs;
That's what the other answers have come up with as well, but in the case where this is called on a temporary object, by the time the function returns you have an (rvalue) reference to an object whose lifetime has ended (undefined behavior).
– Cruz Jean
May 2 at 20:52
@CruzJean Well, my answer was here first and no one downvoted/complained yet so I will keep it here. I am not returning any reference to a temporary anywhere.
– Quimby
May 2 at 20:58
return std::move(logs);
where the return value is a reference type and*this
is a temporary (due to being an rvalue method) makesthis->logs
a temporary as well. That's the reference to a temporary I mean.
– Cruz Jean
May 2 at 22:25
@CruzJean Do you mean e.g.auto&& x = Logger.dumpLogs();
? Yes, that is dangling reference, but that happens for all getters no matter what type of reference they return. My use case would be something likeLogger l; /*calls to log()*/, auto logs = l.dumpLogs();/*log again.. and repeat.*/
– Quimby
2 days ago
add a comment |
I think a use case would be to explicitly give permission to "empty" some non-local variable. Perhaps something like this:
class Logger
public:
void log(const char* msg)
logs.append(msg);
std::vector<std::string>&& dumpLogs()
return std::move(logs);
private:
std::vector<std::string> logs;
;
But I admit I made this up now, I never actually used it and it also can be done like this:
std::vector<std::string> dumpLogs()
auto dumped_logs = logs;
return dumped_logs;
That's what the other answers have come up with as well, but in the case where this is called on a temporary object, by the time the function returns you have an (rvalue) reference to an object whose lifetime has ended (undefined behavior).
– Cruz Jean
May 2 at 20:52
@CruzJean Well, my answer was here first and no one downvoted/complained yet so I will keep it here. I am not returning any reference to a temporary anywhere.
– Quimby
May 2 at 20:58
return std::move(logs);
where the return value is a reference type and*this
is a temporary (due to being an rvalue method) makesthis->logs
a temporary as well. That's the reference to a temporary I mean.
– Cruz Jean
May 2 at 22:25
@CruzJean Do you mean e.g.auto&& x = Logger.dumpLogs();
? Yes, that is dangling reference, but that happens for all getters no matter what type of reference they return. My use case would be something likeLogger l; /*calls to log()*/, auto logs = l.dumpLogs();/*log again.. and repeat.*/
– Quimby
2 days ago
add a comment |
I think a use case would be to explicitly give permission to "empty" some non-local variable. Perhaps something like this:
class Logger
public:
void log(const char* msg)
logs.append(msg);
std::vector<std::string>&& dumpLogs()
return std::move(logs);
private:
std::vector<std::string> logs;
;
But I admit I made this up now, I never actually used it and it also can be done like this:
std::vector<std::string> dumpLogs()
auto dumped_logs = logs;
return dumped_logs;
I think a use case would be to explicitly give permission to "empty" some non-local variable. Perhaps something like this:
class Logger
public:
void log(const char* msg)
logs.append(msg);
std::vector<std::string>&& dumpLogs()
return std::move(logs);
private:
std::vector<std::string> logs;
;
But I admit I made this up now, I never actually used it and it also can be done like this:
std::vector<std::string> dumpLogs()
auto dumped_logs = logs;
return dumped_logs;
answered May 2 at 19:32
QuimbyQuimby
1,297714
1,297714
That's what the other answers have come up with as well, but in the case where this is called on a temporary object, by the time the function returns you have an (rvalue) reference to an object whose lifetime has ended (undefined behavior).
– Cruz Jean
May 2 at 20:52
@CruzJean Well, my answer was here first and no one downvoted/complained yet so I will keep it here. I am not returning any reference to a temporary anywhere.
– Quimby
May 2 at 20:58
return std::move(logs);
where the return value is a reference type and*this
is a temporary (due to being an rvalue method) makesthis->logs
a temporary as well. That's the reference to a temporary I mean.
– Cruz Jean
May 2 at 22:25
@CruzJean Do you mean e.g.auto&& x = Logger.dumpLogs();
? Yes, that is dangling reference, but that happens for all getters no matter what type of reference they return. My use case would be something likeLogger l; /*calls to log()*/, auto logs = l.dumpLogs();/*log again.. and repeat.*/
– Quimby
2 days ago
add a comment |
That's what the other answers have come up with as well, but in the case where this is called on a temporary object, by the time the function returns you have an (rvalue) reference to an object whose lifetime has ended (undefined behavior).
– Cruz Jean
May 2 at 20:52
@CruzJean Well, my answer was here first and no one downvoted/complained yet so I will keep it here. I am not returning any reference to a temporary anywhere.
– Quimby
May 2 at 20:58
return std::move(logs);
where the return value is a reference type and*this
is a temporary (due to being an rvalue method) makesthis->logs
a temporary as well. That's the reference to a temporary I mean.
– Cruz Jean
May 2 at 22:25
@CruzJean Do you mean e.g.auto&& x = Logger.dumpLogs();
? Yes, that is dangling reference, but that happens for all getters no matter what type of reference they return. My use case would be something likeLogger l; /*calls to log()*/, auto logs = l.dumpLogs();/*log again.. and repeat.*/
– Quimby
2 days ago
That's what the other answers have come up with as well, but in the case where this is called on a temporary object, by the time the function returns you have an (rvalue) reference to an object whose lifetime has ended (undefined behavior).
– Cruz Jean
May 2 at 20:52
That's what the other answers have come up with as well, but in the case where this is called on a temporary object, by the time the function returns you have an (rvalue) reference to an object whose lifetime has ended (undefined behavior).
– Cruz Jean
May 2 at 20:52
@CruzJean Well, my answer was here first and no one downvoted/complained yet so I will keep it here. I am not returning any reference to a temporary anywhere.
– Quimby
May 2 at 20:58
@CruzJean Well, my answer was here first and no one downvoted/complained yet so I will keep it here. I am not returning any reference to a temporary anywhere.
– Quimby
May 2 at 20:58
return std::move(logs);
where the return value is a reference type and *this
is a temporary (due to being an rvalue method) makes this->logs
a temporary as well. That's the reference to a temporary I mean.– Cruz Jean
May 2 at 22:25
return std::move(logs);
where the return value is a reference type and *this
is a temporary (due to being an rvalue method) makes this->logs
a temporary as well. That's the reference to a temporary I mean.– Cruz Jean
May 2 at 22:25
@CruzJean Do you mean e.g.
auto&& x = Logger.dumpLogs();
? Yes, that is dangling reference, but that happens for all getters no matter what type of reference they return. My use case would be something like Logger l; /*calls to log()*/, auto logs = l.dumpLogs();/*log again.. and repeat.*/
– Quimby
2 days ago
@CruzJean Do you mean e.g.
auto&& x = Logger.dumpLogs();
? Yes, that is dangling reference, but that happens for all getters no matter what type of reference they return. My use case would be something like Logger l; /*calls to log()*/, auto logs = l.dumpLogs();/*log again.. and repeat.*/
– Quimby
2 days ago
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55958970%2fdoes-it-make-sense-for-a-function-to-return-an-rvalue-reference%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
6
std::move
comes to mind. It certainly returnsT&&
. Edit :std::optional::value
also has anT&&
overload. Edit 2 : It also has aconst T &&
overload, though I'll admit I don't understand the meaning.– François Andrieux
May 2 at 19:32
1
@FrançoisAndrieux the
std::get
family of functions, too.– Brian
May 2 at 19:34
1
See this answer.
– lubgr
May 2 at 19:37
Isn't that a forwarding reference?
– user2357112
May 3 at 1:52