Jump to content

  • Log In with Google      Sign In   
  • Create Account

Interested in a FREE copy of HTML5 game maker Construct 2?

We'll be giving away three Personal Edition licences in next Tuesday's GDNet Direct email newsletter!

Sign up from the right-hand sidebar on our homepage and read Tuesday's newsletter for details!


We're also offering banner ads on our site from just $5! 1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


C++ Function Parameter


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
11 replies to this topic

#1 mic_k   Members   -  Reputation: 122

Like
2Likes
Like

Posted 31 October 2012 - 12:11 AM

hi,
i'm currently in practice with c++, i found a situation(not critical).

as i read from tutorial & article, it said that good thing in passing argument by reference, but not to change the value inside the function, is to use the constant-references as the function parameter.

in situation that i just want to pass the argument to a function just for resource only, not to change the value itself,
1. so when is the right time to use the by-value parameter ?
or
2. when is the time not to use the constant-references parameter ?

may anyone have suggestion..

thank you,
happy coding Posted Image

Sponsor:

#2 Yrjö P.   Crossbones+   -  Reputation: 1412

Like
4Likes
Like

Posted 31 October 2012 - 01:33 AM

in situation that i just want to pass the argument to a function just for resource only, not to change the value itself,
1. so when is the right time to use the by-value parameter ?
or
2. when is the time not to use the constant-references parameter ?

The reason for using const references is to avoid the cost of performing expensive copy operations which occur when passing a complex type by value. Also, some classes outright prevent copying so you couldn't pass objects of those classes by value even if you wanted to. So, always use by-value for built-in types (ints, doubles, pointers, ...), and use const references for arguments with a class type. It's fine to pass simple, copyable classes by value also.

#3 mic_k   Members   -  Reputation: 122

Like
2Likes
Like

Posted 31 October 2012 - 03:15 AM

yes, i also read about that too, use the by-val parameter for built-in types data, use the const-ref for class type data or large list/collection.

and additionally, a consideration when there are needs to copy that function param into local(of function block) variable, some suggested to provide the function with by-value param type.

that give me perspective now, thank you stroppy.

#4 EddieV223   Members   -  Reputation: 1406

Like
0Likes
Like

Posted 31 October 2012 - 07:18 PM

Most of the time you'll pass by reference or pointer in methods, and then copy the value to a classes member variable if you want to hold onto that value.

for example a Vector3 class
[source lang="cpp"]class Vector3{Vector3( double x, double y, double z ) : x(x), y(y), z(z) { }double x;double y;double z;};class Actor{Vector3 mPosition;void SetPosition( const Vector3 & pos ) { mPosition = pos; }};[/source]
this allows you to put in a temporary rvalue when you call the function

someActor.SetPosition( Vector3( 0.0, 0.0, 1.0) );

Which is passed by reference. The difference is that a reference is behind the scenes a pointer. A pointer being up to 64bits on 64bit os. Verses the size of the Vector3 being at least 3 * 64 ( if a double is 64 bits on your system ). This is a optimization. And since when the SetPosition class actually makes use of the reference it copies it, there is no worry about having a invalid reference.

Edited by EddieV223, 31 October 2012 - 07:37 PM.

If this post or signature was helpful and/or constructive please give rep.

 

// C++ Video tutorials

http://www.youtube.com/watch?v=Wo60USYV9Ik

 

// Easy to learn 2D Game Library c++

SFML2.1 Download http://www.sfml-dev.org/download.php

SFML2.1 Tutorials http://www.sfml-dev.org/tutorials/2.1/

 

// SFML 2 book

http://www.amazon.com/gp/product/1849696845/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=1849696845&linkCode=as2&tag=gamer2creator-20

 


#5 Servant of the Lord   Crossbones+   -  Reputation: 20283

Like
2Likes
Like

Posted 31 October 2012 - 07:38 PM

I've posted my opinions on it in this thread (I don't want to copy+paste the large-ish post). Posted Image
It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.
All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.
Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal

[Fly with me on Twitter] [Google+] [My broken website]

[Need web hosting? I personally like A Small Orange]


#6 Yrjö P.   Crossbones+   -  Reputation: 1412

Like
0Likes
Like

Posted 01 November 2012 - 02:34 AM

I've posted my opinions on it in this thread (I don't want to copy+paste the large-ish post). Posted Image

That's about return values, not parameters, though.

Regarding your post on that other thread, you claim that the compiler will use move semantics in a situation where a caller passes a (local?) value as a function parameter and doesn't use that value afterwards. I see how the compiler has a chance to optimize in this situation, but does the standard actually guarantee the compiler will do so? I don't remember reading about such a thing before. It seems like a potentially very expensive and difficult thing for the compiler to detect reliably under all conditions.

#7 Washu   Senior Moderators   -  Reputation: 5359

Like
2Likes
Like

Posted 01 November 2012 - 04:01 AM


I've posted my opinions on it in this thread (I don't want to copy+paste the large-ish post). Posted Image

That's about return values, not parameters, though.

Regarding your post on that other thread, you claim that the compiler will use move semantics in a situation where a caller passes a (local?) value as a function parameter and doesn't use that value afterwards. I see how the compiler has a chance to optimize in this situation, but does the standard actually guarantee the compiler will do so? I don't remember reading about such a thing before. It seems like a potentially very expensive and difficult thing for the compiler to detect reliably under all conditions.

RVO and named RVO are both allowed by the standard. They are not REQUIRED by the standard, no optimizations of any kind are REQUIRED by the standard.

Edited by Washu, 01 November 2012 - 04:01 AM.

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.
ScapeCode - Blog | SlimDX


#8 Yrjö P.   Crossbones+   -  Reputation: 1412

Like
0Likes
Like

Posted 01 November 2012 - 04:58 AM



I've posted my opinions on it in this thread (I don't want to copy+paste the large-ish post). Posted Image

That's about return values, not parameters, though.

Regarding your post on that other thread, you claim that the compiler will use move semantics in a situation where a caller passes a (local?) value as a function parameter and doesn't use that value afterwards. I see how the compiler has a chance to optimize in this situation, but does the standard actually guarantee the compiler will do so? I don't remember reading about such a thing before. It seems like a potentially very expensive and difficult thing for the compiler to detect reliably under all conditions.

RVO and named RVO are both allowed by the standard. They are not REQUIRED by the standard, no optimizations of any kind are REQUIRED by the standard.

Hold on. I wasn't talking about RVO. In Servant of the Lord's example above we have the line:
std::vector<std::string> notACopy = GetStuff(veryLargeVector); //No copy made - not in passing the variable in, and not in return the variable.
For the return value, the standard guarantees that no copy happens. Either RVO is performed *or* the vector is move constructed. The thing I do not fully understand is the claim that veryLargeVector will not be copied when it goes in as a value parameter. Sure, a compiler might notice it will never be used again and use that to optimize (in spite of its lvalue-ness), but do we have an actual guarantee like we do with the return value?

Edited by Stroppy Katamari, 01 November 2012 - 04:59 AM.


#9 Servant of the Lord   Crossbones+   -  Reputation: 20283

Like
0Likes
Like

Posted 01 November 2012 - 09:19 PM


I've posted my opinions on it in this thread (I don't want to copy+paste the large-ish post). Posted Image

That's about return values, not parameters, though.

The thread is about return values primarily, but my post talks about both parameters and return values.

Regarding your post on that other thread, you claim that the compiler will use move semantics in a situation where a caller passes a (local?) value as a function parameter and doesn't use that value afterwards. I see how the compiler has a chance to optimize in this situation, but does the standard actually guarantee the compiler will do so?

I don't remember reading about such a thing before. It seems like a potentially very expensive and difficult thing for the compiler to detect reliably under all conditions.

I was under the impression from the Going Native 2012 videos that it is very likely to use move semantics in that situation, but I was getting confused between lvalues and rvalues. If it was an rvalue, such as an unnamed temporary, it would use move semantics instead of copying (if a move constructor exists for that type). I don't know if it's guaranteed that it will, but I think it would be if the argument type had the proper move constructor.

std::vector<std::string> result = GetStuff(std::vector<std::string>(1000, "very large string containing alot of data");

In this case, since the vector as an argument is an unnamed temporary, my possibly flawed understanding is that it will be guaranteed to be moved instead of copied (if a move constructor exists). Further, my (again: possibly-flawed) understanding that GetStuff(), without RVO, would create a temporary, and then the temporary would be moved into 'result'.

However, you could use std::move() to tell the compiler to move the lvalue and get the same effect: std::move() would take the lvalue and return it as a rvalue, allowing GetStuff() to use a move-constructor for its parameter.

std::vector<std::string> veryLargeVector;
veryLargeVector.resize(2000, "very large string containing alot of data");
std::vector<std::string> result = GetStuff(std::move(veryLargeVector));

It seems all of this would depend on the class being passed around to actually implement move constructors though (which std::vector does).

Where I'm getting my impressions from:
C++11: Rvalue references and move constructors (Wikipedia)
A Brief Introduction to Rvalue References (2008)
GoingNative 2012 - STL11: Magic && Secrets (2012 - Particularly 35 minutes into the video)

I haven't read the actual standard, despite having the PDF draft on my computer.

tl;dr: I was getting confused between lvalues and rvalues, but you can explicitly get the same result if you use std::move() and the type has a move constructor defined. Whether or not a compilers would automaticly detect it (which I recall hearing somewhere, but have no proof of, and it wouldn't be guaranteed), an explicit std::move() should guarantee it.

Edited by Servant of the Lord, 01 November 2012 - 09:22 PM.

It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.
All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.
Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal

[Fly with me on Twitter] [Google+] [My broken website]

[Need web hosting? I personally like A Small Orange]


#10 Yrjö P.   Crossbones+   -  Reputation: 1412

Like
0Likes
Like

Posted 02 November 2012 - 02:57 AM

tl;dr: I was getting confused between lvalues and rvalues, but you can explicitly get the same result if you use std::move() and the type has a move constructor defined. Whether or not a compilers would automaticly detect it (which I recall hearing somewhere, but have no proof of, and it wouldn't be guaranteed), an explicit std::move() should guarantee it.

Thank you, that was an excellent response. (A++++, would reply again, ... Posted Image )
The Lavavej video at exactly 36:53 confirms my earlier point. In your initial example when you passed in a lvalue, you would have gotten a useless copy, contrary to what you initially assumed. I also think you are correct in that applying std::move to the argument would work here, assuming the type has a move constructor. However, the smart default to use is still const ref, and a beginner should just go with that every time instead of trying to puzzle out when to use by-value and when to use move. Moving the argument also leaves the undefined object dangling in the caller and causes the risk of accidentally using it again. I think it's safe to say >90% of people coding C++ for a living do not understand move yet, and a lot of them never will.

#11 Servant of the Lord   Crossbones+   -  Reputation: 20283

Like
0Likes
Like

Posted 02 November 2012 - 09:05 AM

Np, sorry for the initial confusion and spread disinformation. Posted Image
I edited the original post, not to change what I said, but to visually strike-out the wrong info and add a link to this thread.

The Lavavej video at ~35:00 indicates the proper time to use pass-by-value would be when you are creating a copy from the const ref anyway, because then with temporaries the copy can be avoided; as STL puts it in other places: "Never slower, but sometimes faster".

So, general rule of thumb seems to be:
  • Default to const ref, unless...
  • ...you need to modify the original, then default to regular ref
  • ...you need to make a copy, then default to by-value which will sometimes (depending on move constructor) optimize away the copy for temporaries.
Which was pretty much the same rule of thumb C++ has always had. Posted Image
It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.
All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.
Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal

[Fly with me on Twitter] [Google+] [My broken website]

[Need web hosting? I personally like A Small Orange]


#12 Matt-D   Crossbones+   -  Reputation: 1467

Like
0Likes
Like

Posted 05 November 2012 - 05:32 AM

Read this (including the references -- Boris' three-parter "Efficient argument passing in C++11" is linked to in the blog post):
http://scottmeyers.blogspot.com/2012/10/parameter-types-in-constructors.html




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS