Confusion on operator overloading and heap vs stackWhat and where are the stack and heap?What are rvalues, lvalues, xvalues, glvalues, and prvalues?How to return a class object by reference in C++?Why doesn't Java offer operator overloading?What and where are the stack and heap?Which is faster: Stack allocation or Heap allocationWhat is the “-->” operator in C++?What are the basic rules and idioms for operator overloading?Basic operator overloading syntax in c++Confused with Java Memory Management (Stacks and Heaps)Const and Non-Const Operator OverloadingC++ template class and operator overloadingOverloading operator= in templated class
How do conventional missiles fly?
How badly should I try to prevent a user from XSSing themselves?
What method can I use to design a dungeon difficult enough that the PCs can't make it through without killing them?
Apex Framework / library for consuming REST services
What does “the session was packed” mean in this context?
Is it logically or scientifically possible to artificially send energy to the body?
Could the museum Saturn V's be refitted for one more flight?
Why would the Red Woman birth a shadow if she worshipped the Lord of the Light?
Which is the best way to check return result?
Examples of smooth manifolds admitting inbetween one and a continuum of complex structures
If human space travel is limited by the G force vulnerability, is there a way to counter G forces?
How writing a dominant 7 sus4 chord in RNA ( Vsus7 chord in the 1st inversion)
CAST throwing error when run in stored procedure but not when run as raw query
Im going to France and my passport expires June 19th
What mechanic is there to disable a threat instead of killing it?
What killed these X2 caps?
In 'Revenger,' what does 'cove' come from?
Why doesn't using multiple commands with a || or && conditional work?
Expand and Contract
Why didn't Miles's spider sense work before?
Reverse dictionary where values are lists
How dangerous is XSS?
ssTTsSTtRrriinInnnnNNNIiinngg
How does a predictive coding aid in lossless compression?
Confusion on operator overloading and heap vs stack
What and where are the stack and heap?What are rvalues, lvalues, xvalues, glvalues, and prvalues?How to return a class object by reference in C++?Why doesn't Java offer operator overloading?What and where are the stack and heap?Which is faster: Stack allocation or Heap allocationWhat is the “-->” operator in C++?What are the basic rules and idioms for operator overloading?Basic operator overloading syntax in c++Confused with Java Memory Management (Stacks and Heaps)Const and Non-Const Operator OverloadingC++ template class and operator overloadingOverloading operator= in templated class
I'm looking at the following tutorial:
http://www.videotutorialsrock.com/opengl_tutorial/animation/home.php
This person has a vector class:
class Vec3f
private:
float v[3];
public:
Vec3f();
Vec3f(float x, float y, float z);
float &operator[](int index);
float operator[](int index) const;
Vec3f operator*(float scale) const;
Vec3f operator/(float scale) const;
Vec3f operator+(const Vec3f &other) const;
Vec3f operator-(const Vec3f &other) const;
Vec3f operator-() const;
const Vec3f &operator*=(float scale);
const Vec3f &operator/=(float scale);
const Vec3f &operator+=(const Vec3f &other);
const Vec3f &operator-=(const Vec3f &other);
float magnitude() const;
float magnitudeSquared() const;
Vec3f normalize() const;
float dot(const Vec3f &other) const;
Vec3f cross(const Vec3f &other) const;
;
With an example definition:
Vec3f Vec3f::operator*(float scale) const
return Vec3f(v[0] * scale, v[1] * scale, v[2] * scale);
I'm confused on why this works. Shouldn't this immediately cause a segmentation fault? The return value is on the stack and should get deleted upon termination of all of these functions. Why does it work? Is my understanding of stack vs heap incorrect?
EDIT: I am basing my understanding from this:
How to return a class object by reference in C++?
c++ memory-management operator-overloading heap-memory stack-memory
|
show 6 more comments
I'm looking at the following tutorial:
http://www.videotutorialsrock.com/opengl_tutorial/animation/home.php
This person has a vector class:
class Vec3f
private:
float v[3];
public:
Vec3f();
Vec3f(float x, float y, float z);
float &operator[](int index);
float operator[](int index) const;
Vec3f operator*(float scale) const;
Vec3f operator/(float scale) const;
Vec3f operator+(const Vec3f &other) const;
Vec3f operator-(const Vec3f &other) const;
Vec3f operator-() const;
const Vec3f &operator*=(float scale);
const Vec3f &operator/=(float scale);
const Vec3f &operator+=(const Vec3f &other);
const Vec3f &operator-=(const Vec3f &other);
float magnitude() const;
float magnitudeSquared() const;
Vec3f normalize() const;
float dot(const Vec3f &other) const;
Vec3f cross(const Vec3f &other) const;
;
With an example definition:
Vec3f Vec3f::operator*(float scale) const
return Vec3f(v[0] * scale, v[1] * scale, v[2] * scale);
I'm confused on why this works. Shouldn't this immediately cause a segmentation fault? The return value is on the stack and should get deleted upon termination of all of these functions. Why does it work? Is my understanding of stack vs heap incorrect?
EDIT: I am basing my understanding from this:
How to return a class object by reference in C++?
c++ memory-management operator-overloading heap-memory stack-memory
1
If return values got destroyed before the function exited, what would be the point of return values?
– alter igel
Mar 7 at 22:47
1
But it's not being returned by reference. This is a plain old return by value. The object is being copied and it is trivially copyable so there's not much that can go wrong. Plus there is a lot of room for the compiler to eliminate the copy (See Copy Elision).
– user4581301
Mar 7 at 22:51
2
return by reference != return by copy/value. If you were returning by reference, you would indeed have undefined behavior (UB).
– Jarod42
Mar 7 at 22:51
2
@SpentDeath if yourVec3f
had dynamically allocated member data, and followed the Rule of Three, then yes, it would be perfectly safe.
– alter igel
Mar 7 at 22:54
2
But if you do not follow the Rule of Three, then you are very likely smurfed one way or another. You have a memory leak or sooner or later there is a double delete. Your goal as a programmer should be to design your classes to observe the Rule of zero or hide all of the management through the Rules of Three and Five from users to that they can adhere to the Rule of Zero.
– user4581301
Mar 7 at 22:57
|
show 6 more comments
I'm looking at the following tutorial:
http://www.videotutorialsrock.com/opengl_tutorial/animation/home.php
This person has a vector class:
class Vec3f
private:
float v[3];
public:
Vec3f();
Vec3f(float x, float y, float z);
float &operator[](int index);
float operator[](int index) const;
Vec3f operator*(float scale) const;
Vec3f operator/(float scale) const;
Vec3f operator+(const Vec3f &other) const;
Vec3f operator-(const Vec3f &other) const;
Vec3f operator-() const;
const Vec3f &operator*=(float scale);
const Vec3f &operator/=(float scale);
const Vec3f &operator+=(const Vec3f &other);
const Vec3f &operator-=(const Vec3f &other);
float magnitude() const;
float magnitudeSquared() const;
Vec3f normalize() const;
float dot(const Vec3f &other) const;
Vec3f cross(const Vec3f &other) const;
;
With an example definition:
Vec3f Vec3f::operator*(float scale) const
return Vec3f(v[0] * scale, v[1] * scale, v[2] * scale);
I'm confused on why this works. Shouldn't this immediately cause a segmentation fault? The return value is on the stack and should get deleted upon termination of all of these functions. Why does it work? Is my understanding of stack vs heap incorrect?
EDIT: I am basing my understanding from this:
How to return a class object by reference in C++?
c++ memory-management operator-overloading heap-memory stack-memory
I'm looking at the following tutorial:
http://www.videotutorialsrock.com/opengl_tutorial/animation/home.php
This person has a vector class:
class Vec3f
private:
float v[3];
public:
Vec3f();
Vec3f(float x, float y, float z);
float &operator[](int index);
float operator[](int index) const;
Vec3f operator*(float scale) const;
Vec3f operator/(float scale) const;
Vec3f operator+(const Vec3f &other) const;
Vec3f operator-(const Vec3f &other) const;
Vec3f operator-() const;
const Vec3f &operator*=(float scale);
const Vec3f &operator/=(float scale);
const Vec3f &operator+=(const Vec3f &other);
const Vec3f &operator-=(const Vec3f &other);
float magnitude() const;
float magnitudeSquared() const;
Vec3f normalize() const;
float dot(const Vec3f &other) const;
Vec3f cross(const Vec3f &other) const;
;
With an example definition:
Vec3f Vec3f::operator*(float scale) const
return Vec3f(v[0] * scale, v[1] * scale, v[2] * scale);
I'm confused on why this works. Shouldn't this immediately cause a segmentation fault? The return value is on the stack and should get deleted upon termination of all of these functions. Why does it work? Is my understanding of stack vs heap incorrect?
EDIT: I am basing my understanding from this:
How to return a class object by reference in C++?
c++ memory-management operator-overloading heap-memory stack-memory
c++ memory-management operator-overloading heap-memory stack-memory
edited Mar 7 at 22:50
Spent Death
asked Mar 7 at 22:40
Spent DeathSpent Death
295311
295311
1
If return values got destroyed before the function exited, what would be the point of return values?
– alter igel
Mar 7 at 22:47
1
But it's not being returned by reference. This is a plain old return by value. The object is being copied and it is trivially copyable so there's not much that can go wrong. Plus there is a lot of room for the compiler to eliminate the copy (See Copy Elision).
– user4581301
Mar 7 at 22:51
2
return by reference != return by copy/value. If you were returning by reference, you would indeed have undefined behavior (UB).
– Jarod42
Mar 7 at 22:51
2
@SpentDeath if yourVec3f
had dynamically allocated member data, and followed the Rule of Three, then yes, it would be perfectly safe.
– alter igel
Mar 7 at 22:54
2
But if you do not follow the Rule of Three, then you are very likely smurfed one way or another. You have a memory leak or sooner or later there is a double delete. Your goal as a programmer should be to design your classes to observe the Rule of zero or hide all of the management through the Rules of Three and Five from users to that they can adhere to the Rule of Zero.
– user4581301
Mar 7 at 22:57
|
show 6 more comments
1
If return values got destroyed before the function exited, what would be the point of return values?
– alter igel
Mar 7 at 22:47
1
But it's not being returned by reference. This is a plain old return by value. The object is being copied and it is trivially copyable so there's not much that can go wrong. Plus there is a lot of room for the compiler to eliminate the copy (See Copy Elision).
– user4581301
Mar 7 at 22:51
2
return by reference != return by copy/value. If you were returning by reference, you would indeed have undefined behavior (UB).
– Jarod42
Mar 7 at 22:51
2
@SpentDeath if yourVec3f
had dynamically allocated member data, and followed the Rule of Three, then yes, it would be perfectly safe.
– alter igel
Mar 7 at 22:54
2
But if you do not follow the Rule of Three, then you are very likely smurfed one way or another. You have a memory leak or sooner or later there is a double delete. Your goal as a programmer should be to design your classes to observe the Rule of zero or hide all of the management through the Rules of Three and Five from users to that they can adhere to the Rule of Zero.
– user4581301
Mar 7 at 22:57
1
1
If return values got destroyed before the function exited, what would be the point of return values?
– alter igel
Mar 7 at 22:47
If return values got destroyed before the function exited, what would be the point of return values?
– alter igel
Mar 7 at 22:47
1
1
But it's not being returned by reference. This is a plain old return by value. The object is being copied and it is trivially copyable so there's not much that can go wrong. Plus there is a lot of room for the compiler to eliminate the copy (See Copy Elision).
– user4581301
Mar 7 at 22:51
But it's not being returned by reference. This is a plain old return by value. The object is being copied and it is trivially copyable so there's not much that can go wrong. Plus there is a lot of room for the compiler to eliminate the copy (See Copy Elision).
– user4581301
Mar 7 at 22:51
2
2
return by reference != return by copy/value. If you were returning by reference, you would indeed have undefined behavior (UB).
– Jarod42
Mar 7 at 22:51
return by reference != return by copy/value. If you were returning by reference, you would indeed have undefined behavior (UB).
– Jarod42
Mar 7 at 22:51
2
2
@SpentDeath if your
Vec3f
had dynamically allocated member data, and followed the Rule of Three, then yes, it would be perfectly safe.– alter igel
Mar 7 at 22:54
@SpentDeath if your
Vec3f
had dynamically allocated member data, and followed the Rule of Three, then yes, it would be perfectly safe.– alter igel
Mar 7 at 22:54
2
2
But if you do not follow the Rule of Three, then you are very likely smurfed one way or another. You have a memory leak or sooner or later there is a double delete. Your goal as a programmer should be to design your classes to observe the Rule of zero or hide all of the management through the Rules of Three and Five from users to that they can adhere to the Rule of Zero.
– user4581301
Mar 7 at 22:57
But if you do not follow the Rule of Three, then you are very likely smurfed one way or another. You have a memory leak or sooner or later there is a double delete. Your goal as a programmer should be to design your classes to observe the Rule of zero or hide all of the management through the Rules of Three and Five from users to that they can adhere to the Rule of Zero.
– user4581301
Mar 7 at 22:57
|
show 6 more comments
4 Answers
4
active
oldest
votes
You can look in the following example:
Vec3f Vec3f::operator*(float scale) const
return Vec3f(v[0] * scale, v[1] * scale, v[2] * scale);
Vec3f a(1,2,3);
Vec3f b;
b = a * 2;
In general the following will happen:
the operator overload implementation will construct a new instance of the Ve3f with the new arguments, representing multiplication.
the return procedure will call a default copy constructor of
b
with the constructed object in the argument. The copy-constructor will copy fields from its argument to the instance of 'b'.
You can always implement your own copy constructor to do something else besides the shallow copy which the default one provides.
Vec3f(const Ver3f &src)...
So, as a result you will get a new objects with all fields copied from the one created at the return statement. This is the return by value as defined in c++ for objects.
The result would be different if you returned the object by a pointer or a reference. It will cause a memory corruption.
You can always implement your own copy constructor to do something else besides the shallow copy which the default one provides -- For the OP's case, thedefault
versions of the copy constructor, assignment operator, and destructor are perfectly fine, since the only member is an array of 3 float's. Writing versions of these functions when there is no need to can lead to bugs or code that may not be optimized.
– PaulMcKenzie
Mar 8 at 4:13
add a comment |
Vec3f Vec3f::operator*(float scale) const
return Vec3f(v[0] * scale, v[1] * scale, v[2] * scale);
This uses return by value, so what is returned is the value of the class instance created by that line, not the instance itself.
This is fundamentally no different from return 1;
. The value one is returned, not any particular instance or class member that contains that value. As with pretty much everything else, it's the implementation's responsibility to figure out how to accomplish what the code asks for -- in this case, ensuring that some instance exists to hold the returned value with an appropriate lifetime.
add a comment |
That's the binary multiplication operator, and it's returning a copy of the data in the Vec3f
instance, multiplied by float scale
, into an rvalue for use by the rest of an expression.
How that works is already answered in What are rvalues, lvalues, xvalues, glvalues, and prvalues?
Also see https://en.cppreference.com/w/cpp/language/operator_arithmetic
1
By dereference operator, do you mean the unaryoperator*
? OP's function clearly uses afloat scale
argument, which makes this the infixoperator*
. Also, I really don't think value categories shed any light on how return values work with the stack.
– alter igel
Mar 7 at 22:49
If you consider a duplicate, vote to close as it.
– Jarod42
Mar 7 at 22:50
Oh, interesting. You're right, I missed that. I'll change the operator mentioned. That said, it does return an rvalue, and understanding how return values work is still best covered by the other question, and is probably a useful read for OP. I did mark this as a duplicate.
– Tzalumen
Mar 7 at 22:53
add a comment |
So, every cpu has it's own calling convention. For more detailed info look into this and this
Basically, the return value, or the address to the return value is copied to the a register like R0 in ARM and EAX in x86 so the caller of the function can access it.
Whatever calling convention is being used is an implementation detail of the compiler. That's beyond the scope of the rules of the C++ language and has nothing to do with what a program means in terms of the language.
– alter igel
Mar 7 at 23:00
even if the code is in C++, the question is general and about heap and stack. they're generally wondering how values are returned and told them how.
– Mohammad
Mar 7 at 23:05
Then can you explain how the calling convention distinguishes returning by value versus returning by reference in C++, and what the calling convention does to ensure the existence of the returned object?
– alter igel
Mar 7 at 23:12
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%2f55053963%2fconfusion-on-operator-overloading-and-heap-vs-stack%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
You can look in the following example:
Vec3f Vec3f::operator*(float scale) const
return Vec3f(v[0] * scale, v[1] * scale, v[2] * scale);
Vec3f a(1,2,3);
Vec3f b;
b = a * 2;
In general the following will happen:
the operator overload implementation will construct a new instance of the Ve3f with the new arguments, representing multiplication.
the return procedure will call a default copy constructor of
b
with the constructed object in the argument. The copy-constructor will copy fields from its argument to the instance of 'b'.
You can always implement your own copy constructor to do something else besides the shallow copy which the default one provides.
Vec3f(const Ver3f &src)...
So, as a result you will get a new objects with all fields copied from the one created at the return statement. This is the return by value as defined in c++ for objects.
The result would be different if you returned the object by a pointer or a reference. It will cause a memory corruption.
You can always implement your own copy constructor to do something else besides the shallow copy which the default one provides -- For the OP's case, thedefault
versions of the copy constructor, assignment operator, and destructor are perfectly fine, since the only member is an array of 3 float's. Writing versions of these functions when there is no need to can lead to bugs or code that may not be optimized.
– PaulMcKenzie
Mar 8 at 4:13
add a comment |
You can look in the following example:
Vec3f Vec3f::operator*(float scale) const
return Vec3f(v[0] * scale, v[1] * scale, v[2] * scale);
Vec3f a(1,2,3);
Vec3f b;
b = a * 2;
In general the following will happen:
the operator overload implementation will construct a new instance of the Ve3f with the new arguments, representing multiplication.
the return procedure will call a default copy constructor of
b
with the constructed object in the argument. The copy-constructor will copy fields from its argument to the instance of 'b'.
You can always implement your own copy constructor to do something else besides the shallow copy which the default one provides.
Vec3f(const Ver3f &src)...
So, as a result you will get a new objects with all fields copied from the one created at the return statement. This is the return by value as defined in c++ for objects.
The result would be different if you returned the object by a pointer or a reference. It will cause a memory corruption.
You can always implement your own copy constructor to do something else besides the shallow copy which the default one provides -- For the OP's case, thedefault
versions of the copy constructor, assignment operator, and destructor are perfectly fine, since the only member is an array of 3 float's. Writing versions of these functions when there is no need to can lead to bugs or code that may not be optimized.
– PaulMcKenzie
Mar 8 at 4:13
add a comment |
You can look in the following example:
Vec3f Vec3f::operator*(float scale) const
return Vec3f(v[0] * scale, v[1] * scale, v[2] * scale);
Vec3f a(1,2,3);
Vec3f b;
b = a * 2;
In general the following will happen:
the operator overload implementation will construct a new instance of the Ve3f with the new arguments, representing multiplication.
the return procedure will call a default copy constructor of
b
with the constructed object in the argument. The copy-constructor will copy fields from its argument to the instance of 'b'.
You can always implement your own copy constructor to do something else besides the shallow copy which the default one provides.
Vec3f(const Ver3f &src)...
So, as a result you will get a new objects with all fields copied from the one created at the return statement. This is the return by value as defined in c++ for objects.
The result would be different if you returned the object by a pointer or a reference. It will cause a memory corruption.
You can look in the following example:
Vec3f Vec3f::operator*(float scale) const
return Vec3f(v[0] * scale, v[1] * scale, v[2] * scale);
Vec3f a(1,2,3);
Vec3f b;
b = a * 2;
In general the following will happen:
the operator overload implementation will construct a new instance of the Ve3f with the new arguments, representing multiplication.
the return procedure will call a default copy constructor of
b
with the constructed object in the argument. The copy-constructor will copy fields from its argument to the instance of 'b'.
You can always implement your own copy constructor to do something else besides the shallow copy which the default one provides.
Vec3f(const Ver3f &src)...
So, as a result you will get a new objects with all fields copied from the one created at the return statement. This is the return by value as defined in c++ for objects.
The result would be different if you returned the object by a pointer or a reference. It will cause a memory corruption.
answered Mar 8 at 3:26
SergeSerge
4,12221016
4,12221016
You can always implement your own copy constructor to do something else besides the shallow copy which the default one provides -- For the OP's case, thedefault
versions of the copy constructor, assignment operator, and destructor are perfectly fine, since the only member is an array of 3 float's. Writing versions of these functions when there is no need to can lead to bugs or code that may not be optimized.
– PaulMcKenzie
Mar 8 at 4:13
add a comment |
You can always implement your own copy constructor to do something else besides the shallow copy which the default one provides -- For the OP's case, thedefault
versions of the copy constructor, assignment operator, and destructor are perfectly fine, since the only member is an array of 3 float's. Writing versions of these functions when there is no need to can lead to bugs or code that may not be optimized.
– PaulMcKenzie
Mar 8 at 4:13
You can always implement your own copy constructor to do something else besides the shallow copy which the default one provides -- For the OP's case, the
default
versions of the copy constructor, assignment operator, and destructor are perfectly fine, since the only member is an array of 3 float's. Writing versions of these functions when there is no need to can lead to bugs or code that may not be optimized.– PaulMcKenzie
Mar 8 at 4:13
You can always implement your own copy constructor to do something else besides the shallow copy which the default one provides -- For the OP's case, the
default
versions of the copy constructor, assignment operator, and destructor are perfectly fine, since the only member is an array of 3 float's. Writing versions of these functions when there is no need to can lead to bugs or code that may not be optimized.– PaulMcKenzie
Mar 8 at 4:13
add a comment |
Vec3f Vec3f::operator*(float scale) const
return Vec3f(v[0] * scale, v[1] * scale, v[2] * scale);
This uses return by value, so what is returned is the value of the class instance created by that line, not the instance itself.
This is fundamentally no different from return 1;
. The value one is returned, not any particular instance or class member that contains that value. As with pretty much everything else, it's the implementation's responsibility to figure out how to accomplish what the code asks for -- in this case, ensuring that some instance exists to hold the returned value with an appropriate lifetime.
add a comment |
Vec3f Vec3f::operator*(float scale) const
return Vec3f(v[0] * scale, v[1] * scale, v[2] * scale);
This uses return by value, so what is returned is the value of the class instance created by that line, not the instance itself.
This is fundamentally no different from return 1;
. The value one is returned, not any particular instance or class member that contains that value. As with pretty much everything else, it's the implementation's responsibility to figure out how to accomplish what the code asks for -- in this case, ensuring that some instance exists to hold the returned value with an appropriate lifetime.
add a comment |
Vec3f Vec3f::operator*(float scale) const
return Vec3f(v[0] * scale, v[1] * scale, v[2] * scale);
This uses return by value, so what is returned is the value of the class instance created by that line, not the instance itself.
This is fundamentally no different from return 1;
. The value one is returned, not any particular instance or class member that contains that value. As with pretty much everything else, it's the implementation's responsibility to figure out how to accomplish what the code asks for -- in this case, ensuring that some instance exists to hold the returned value with an appropriate lifetime.
Vec3f Vec3f::operator*(float scale) const
return Vec3f(v[0] * scale, v[1] * scale, v[2] * scale);
This uses return by value, so what is returned is the value of the class instance created by that line, not the instance itself.
This is fundamentally no different from return 1;
. The value one is returned, not any particular instance or class member that contains that value. As with pretty much everything else, it's the implementation's responsibility to figure out how to accomplish what the code asks for -- in this case, ensuring that some instance exists to hold the returned value with an appropriate lifetime.
edited Mar 7 at 23:11
answered Mar 7 at 22:54
David SchwartzDavid Schwartz
139k14145230
139k14145230
add a comment |
add a comment |
That's the binary multiplication operator, and it's returning a copy of the data in the Vec3f
instance, multiplied by float scale
, into an rvalue for use by the rest of an expression.
How that works is already answered in What are rvalues, lvalues, xvalues, glvalues, and prvalues?
Also see https://en.cppreference.com/w/cpp/language/operator_arithmetic
1
By dereference operator, do you mean the unaryoperator*
? OP's function clearly uses afloat scale
argument, which makes this the infixoperator*
. Also, I really don't think value categories shed any light on how return values work with the stack.
– alter igel
Mar 7 at 22:49
If you consider a duplicate, vote to close as it.
– Jarod42
Mar 7 at 22:50
Oh, interesting. You're right, I missed that. I'll change the operator mentioned. That said, it does return an rvalue, and understanding how return values work is still best covered by the other question, and is probably a useful read for OP. I did mark this as a duplicate.
– Tzalumen
Mar 7 at 22:53
add a comment |
That's the binary multiplication operator, and it's returning a copy of the data in the Vec3f
instance, multiplied by float scale
, into an rvalue for use by the rest of an expression.
How that works is already answered in What are rvalues, lvalues, xvalues, glvalues, and prvalues?
Also see https://en.cppreference.com/w/cpp/language/operator_arithmetic
1
By dereference operator, do you mean the unaryoperator*
? OP's function clearly uses afloat scale
argument, which makes this the infixoperator*
. Also, I really don't think value categories shed any light on how return values work with the stack.
– alter igel
Mar 7 at 22:49
If you consider a duplicate, vote to close as it.
– Jarod42
Mar 7 at 22:50
Oh, interesting. You're right, I missed that. I'll change the operator mentioned. That said, it does return an rvalue, and understanding how return values work is still best covered by the other question, and is probably a useful read for OP. I did mark this as a duplicate.
– Tzalumen
Mar 7 at 22:53
add a comment |
That's the binary multiplication operator, and it's returning a copy of the data in the Vec3f
instance, multiplied by float scale
, into an rvalue for use by the rest of an expression.
How that works is already answered in What are rvalues, lvalues, xvalues, glvalues, and prvalues?
Also see https://en.cppreference.com/w/cpp/language/operator_arithmetic
That's the binary multiplication operator, and it's returning a copy of the data in the Vec3f
instance, multiplied by float scale
, into an rvalue for use by the rest of an expression.
How that works is already answered in What are rvalues, lvalues, xvalues, glvalues, and prvalues?
Also see https://en.cppreference.com/w/cpp/language/operator_arithmetic
edited Mar 7 at 22:57
answered Mar 7 at 22:47
TzalumenTzalumen
486212
486212
1
By dereference operator, do you mean the unaryoperator*
? OP's function clearly uses afloat scale
argument, which makes this the infixoperator*
. Also, I really don't think value categories shed any light on how return values work with the stack.
– alter igel
Mar 7 at 22:49
If you consider a duplicate, vote to close as it.
– Jarod42
Mar 7 at 22:50
Oh, interesting. You're right, I missed that. I'll change the operator mentioned. That said, it does return an rvalue, and understanding how return values work is still best covered by the other question, and is probably a useful read for OP. I did mark this as a duplicate.
– Tzalumen
Mar 7 at 22:53
add a comment |
1
By dereference operator, do you mean the unaryoperator*
? OP's function clearly uses afloat scale
argument, which makes this the infixoperator*
. Also, I really don't think value categories shed any light on how return values work with the stack.
– alter igel
Mar 7 at 22:49
If you consider a duplicate, vote to close as it.
– Jarod42
Mar 7 at 22:50
Oh, interesting. You're right, I missed that. I'll change the operator mentioned. That said, it does return an rvalue, and understanding how return values work is still best covered by the other question, and is probably a useful read for OP. I did mark this as a duplicate.
– Tzalumen
Mar 7 at 22:53
1
1
By dereference operator, do you mean the unary
operator*
? OP's function clearly uses a float scale
argument, which makes this the infix operator*
. Also, I really don't think value categories shed any light on how return values work with the stack.– alter igel
Mar 7 at 22:49
By dereference operator, do you mean the unary
operator*
? OP's function clearly uses a float scale
argument, which makes this the infix operator*
. Also, I really don't think value categories shed any light on how return values work with the stack.– alter igel
Mar 7 at 22:49
If you consider a duplicate, vote to close as it.
– Jarod42
Mar 7 at 22:50
If you consider a duplicate, vote to close as it.
– Jarod42
Mar 7 at 22:50
Oh, interesting. You're right, I missed that. I'll change the operator mentioned. That said, it does return an rvalue, and understanding how return values work is still best covered by the other question, and is probably a useful read for OP. I did mark this as a duplicate.
– Tzalumen
Mar 7 at 22:53
Oh, interesting. You're right, I missed that. I'll change the operator mentioned. That said, it does return an rvalue, and understanding how return values work is still best covered by the other question, and is probably a useful read for OP. I did mark this as a duplicate.
– Tzalumen
Mar 7 at 22:53
add a comment |
So, every cpu has it's own calling convention. For more detailed info look into this and this
Basically, the return value, or the address to the return value is copied to the a register like R0 in ARM and EAX in x86 so the caller of the function can access it.
Whatever calling convention is being used is an implementation detail of the compiler. That's beyond the scope of the rules of the C++ language and has nothing to do with what a program means in terms of the language.
– alter igel
Mar 7 at 23:00
even if the code is in C++, the question is general and about heap and stack. they're generally wondering how values are returned and told them how.
– Mohammad
Mar 7 at 23:05
Then can you explain how the calling convention distinguishes returning by value versus returning by reference in C++, and what the calling convention does to ensure the existence of the returned object?
– alter igel
Mar 7 at 23:12
add a comment |
So, every cpu has it's own calling convention. For more detailed info look into this and this
Basically, the return value, or the address to the return value is copied to the a register like R0 in ARM and EAX in x86 so the caller of the function can access it.
Whatever calling convention is being used is an implementation detail of the compiler. That's beyond the scope of the rules of the C++ language and has nothing to do with what a program means in terms of the language.
– alter igel
Mar 7 at 23:00
even if the code is in C++, the question is general and about heap and stack. they're generally wondering how values are returned and told them how.
– Mohammad
Mar 7 at 23:05
Then can you explain how the calling convention distinguishes returning by value versus returning by reference in C++, and what the calling convention does to ensure the existence of the returned object?
– alter igel
Mar 7 at 23:12
add a comment |
So, every cpu has it's own calling convention. For more detailed info look into this and this
Basically, the return value, or the address to the return value is copied to the a register like R0 in ARM and EAX in x86 so the caller of the function can access it.
So, every cpu has it's own calling convention. For more detailed info look into this and this
Basically, the return value, or the address to the return value is copied to the a register like R0 in ARM and EAX in x86 so the caller of the function can access it.
answered Mar 7 at 22:54
MohammadMohammad
248
248
Whatever calling convention is being used is an implementation detail of the compiler. That's beyond the scope of the rules of the C++ language and has nothing to do with what a program means in terms of the language.
– alter igel
Mar 7 at 23:00
even if the code is in C++, the question is general and about heap and stack. they're generally wondering how values are returned and told them how.
– Mohammad
Mar 7 at 23:05
Then can you explain how the calling convention distinguishes returning by value versus returning by reference in C++, and what the calling convention does to ensure the existence of the returned object?
– alter igel
Mar 7 at 23:12
add a comment |
Whatever calling convention is being used is an implementation detail of the compiler. That's beyond the scope of the rules of the C++ language and has nothing to do with what a program means in terms of the language.
– alter igel
Mar 7 at 23:00
even if the code is in C++, the question is general and about heap and stack. they're generally wondering how values are returned and told them how.
– Mohammad
Mar 7 at 23:05
Then can you explain how the calling convention distinguishes returning by value versus returning by reference in C++, and what the calling convention does to ensure the existence of the returned object?
– alter igel
Mar 7 at 23:12
Whatever calling convention is being used is an implementation detail of the compiler. That's beyond the scope of the rules of the C++ language and has nothing to do with what a program means in terms of the language.
– alter igel
Mar 7 at 23:00
Whatever calling convention is being used is an implementation detail of the compiler. That's beyond the scope of the rules of the C++ language and has nothing to do with what a program means in terms of the language.
– alter igel
Mar 7 at 23:00
even if the code is in C++, the question is general and about heap and stack. they're generally wondering how values are returned and told them how.
– Mohammad
Mar 7 at 23:05
even if the code is in C++, the question is general and about heap and stack. they're generally wondering how values are returned and told them how.
– Mohammad
Mar 7 at 23:05
Then can you explain how the calling convention distinguishes returning by value versus returning by reference in C++, and what the calling convention does to ensure the existence of the returned object?
– alter igel
Mar 7 at 23:12
Then can you explain how the calling convention distinguishes returning by value versus returning by reference in C++, and what the calling convention does to ensure the existence of the returned object?
– alter igel
Mar 7 at 23:12
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%2f55053963%2fconfusion-on-operator-overloading-and-heap-vs-stack%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
1
If return values got destroyed before the function exited, what would be the point of return values?
– alter igel
Mar 7 at 22:47
1
But it's not being returned by reference. This is a plain old return by value. The object is being copied and it is trivially copyable so there's not much that can go wrong. Plus there is a lot of room for the compiler to eliminate the copy (See Copy Elision).
– user4581301
Mar 7 at 22:51
2
return by reference != return by copy/value. If you were returning by reference, you would indeed have undefined behavior (UB).
– Jarod42
Mar 7 at 22:51
2
@SpentDeath if your
Vec3f
had dynamically allocated member data, and followed the Rule of Three, then yes, it would be perfectly safe.– alter igel
Mar 7 at 22:54
2
But if you do not follow the Rule of Three, then you are very likely smurfed one way or another. You have a memory leak or sooner or later there is a double delete. Your goal as a programmer should be to design your classes to observe the Rule of zero or hide all of the management through the Rules of Three and Five from users to that they can adhere to the Rule of Zero.
– user4581301
Mar 7 at 22:57