Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Call by value vs. Call by reference

Reply
Thread Tools

Call by value vs. Call by reference

 
 
Saeed Amrollahi
Guest
Posts: n/a
 
      07-11-2008
Dear All
Hi

I have learned when an object is big, I should pass the object using a
reference or pointer to it rather than calling by value.
In the following code, I don't gain cosiderable performance with call-
by-reference vs. call-by-value. Indeed, the perforamnce is absolutely
unconsiderable:

#include <vector>
#include <iostream>

using namespace std;
void f1(std::vector<int> v)
{
cout << "f1 called" << '\n';
for (std::vector<int>::size_type sz = 0; sz < v.size(); sz++)
v[sz] = sz;
cout << "f1 end" << '\n';
}

void f2(std::vector<int> v)
{
cout << "f2 called" << '\n';
for (std::vector<int>::size_type sz = 0; sz < v.size(); sz++)
v[sz] = sz;
cout << "f2 end" << '\n';
}

void f3(std::vector<int>* pv)
{
cout << "f3 called" << '\n';
for (std::vector<int>::size_type sz = 0; sz < pv->size(); sz++)
(*pv)[sz] = sz;
cout << "f3 end" << '\n';
}
int main()
{
vector<int> v(50000000);
f1(v);
f2(v);
f3(&v);

return 0;
}

I ran under Visual Studio 2005, Visual Studio 2008 and GCC. Is it
about some compiler switches that I should on/off? Did compilers
become more clever?

In advance, thank you for your comments.
- Saeed Amrollahi
 
Reply With Quote
 
 
 
 
Ron AF Greve
Guest
Posts: n/a
 
      07-11-2008
Hi,


I would expect you see a large difference since if you pass by value it has
to copy the whole vecor, however..

In your code the compiler might have removed the whole vector copying during
optimization since you don't do anything with it. You wouldn't notice a
difference between a program with the vector passed in and one completely
without and without assignment

Regards, Ron AF Greve

http://www.InformationSuperHighway.eu

"Saeed Amrollahi" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> Dear All
> Hi
>
> I have learned when an object is big, I should pass the object using a
> reference or pointer to it rather than calling by value.
> In the following code, I don't gain cosiderable performance with call-
> by-reference vs. call-by-value. Indeed, the perforamnce is absolutely
> unconsiderable:
>
> #include <vector>
> #include <iostream>
>
> using namespace std;
> void f1(std::vector<int> v)
> {
> cout << "f1 called" << '\n';
> for (std::vector<int>::size_type sz = 0; sz < v.size(); sz++)
> v[sz] = sz;
> cout << "f1 end" << '\n';
> }
>
> void f2(std::vector<int> v)
> {
> cout << "f2 called" << '\n';
> for (std::vector<int>::size_type sz = 0; sz < v.size(); sz++)
> v[sz] = sz;
> cout << "f2 end" << '\n';
> }
>
> void f3(std::vector<int>* pv)
> {
> cout << "f3 called" << '\n';
> for (std::vector<int>::size_type sz = 0; sz < pv->size(); sz++)
> (*pv)[sz] = sz;
> cout << "f3 end" << '\n';
> }
> int main()
> {
> vector<int> v(50000000);
> f1(v);
> f2(v);
> f3(&v);
>
> return 0;
> }
>
> I ran under Visual Studio 2005, Visual Studio 2008 and GCC. Is it
> about some compiler switches that I should on/off? Did compilers
> become more clever?
>
> In advance, thank you for your comments.
> - Saeed Amrollahi



 
Reply With Quote
 
 
 
 
Soumen
Guest
Posts: n/a
 
      07-11-2008
On Jul 11, 1:37*pm, Saeed Amrollahi <(E-Mail Removed)> wrote:
> Dear All
> Hi
>
> I have learned when an object is big, I should pass the object using a
> reference or pointer to it rather than calling by value.
> In the following code, I don't gain cosiderable performance with call-
> by-reference vs. call-by-value. Indeed, the perforamnce is absolutely
> unconsiderable:
>
> #include <vector>
> #include <iostream>
>
> using namespace std;
> void f1(std::vector<int> v)
> {
> * * * * cout << "f1 called" << '\n';
> * * * * for (std::vector<int>::size_type sz = 0; sz < v.size(); sz++)
> * * * * * * * * v[sz] = sz;
> * * * * cout << "f1 end" << '\n';
>
> }
>
> void f2(std::vector<int> v)
> {
> * * * * cout << "f2 called" << '\n';
> * * * * for (std::vector<int>::size_type sz = 0; sz < v.size(); sz++)
> * * * * * * * * v[sz] = sz;
> * * * * cout << "f2 end" << '\n';
>
> }
>
> void f3(std::vector<int>* pv)
> {
> * * * * cout << "f3 called" << '\n';
> * * * * for (std::vector<int>::size_type sz = 0; sz < pv->size(); sz++)
> * * * * * * * * (*pv)[sz] = sz;
> * * * * cout << "f3 end" << '\n';}
>
> int main()
> {
> * * * * vector<int> v(50000000);
> * * * * f1(v);
> * * * * f2(v);
> * * * * * * * * f3(&v);
>
> * * * * return 0;
>
> }
>
> I ran under Visual Studio 2005, Visual Studio 2008 and GCC. Is it
> about some compiler switches that I should on/off? Did compilers
> become more clever?
>
> In advance, thank you for your comments.
> *- Saeed Amrollahi


Probably because your vector is empty (may be it's just holding a
pointer and few other int)and you're inserting elements inside the
function.
Try inserting elements before calling the function and call the
function 1000 times or so. Also try vector of string and let it have
all same
elements. Let me know what you find.

Regards,
~ Soumen
 
Reply With Quote
 
Juha Nieminen
Guest
Posts: n/a
 
      07-11-2008
Saeed Amrollahi wrote:
> I have learned when an object is big, I should pass the object using a
> reference or pointer to it rather than calling by value.
> In the following code, I don't gain cosiderable performance with call-
> by-reference vs. call-by-value. Indeed, the perforamnce is absolutely
> unconsiderable:


How do you measure the speed of the program? Maybe copying that vector
is relatively so fast that you don't notice the difference. Try calling
each function in a loop to see if there's a difference.
 
Reply With Quote
 
acehreli@gmail.com
Guest
Posts: n/a
 
      07-11-2008
On Jul 11, 7:08*am, Soumen <(E-Mail Removed)> wrote:
> On Jul 11, 1:37*pm, Saeed Amrollahi <(E-Mail Removed)> wrote:


> > void f1(std::vector<int> v)
> > {
> > * * * * cout << "f1 called" << '\n';
> > * * * * for (std::vector<int>::size_type sz = 0; sz < v.size(); sz++)
> > * * * * * * * * v[sz] = sz;


That is not "inserting" an element, rather assigning to an existing
one.

> > * * * * cout << "f1 end" << '\n';

>
> > }


> > * * * * vector<int> v(50000000);


That is a vector with 50 million ints, not empty.

> Probably because your vector is empty (may be it's just holding a
> pointer and few other int)and you're inserting elements inside the
> function.


That would be this code:

vector<int> v; // empty
/* ... */
v.push_back(sz); // insert

Ali
 
Reply With Quote
 
Thomas J. Gritzan
Guest
Posts: n/a
 
      07-11-2008
Saeed Amrollahi schrieb:
> Dear All
> Hi
>
> I have learned when an object is big, I should pass the object using a
> reference or pointer to it rather than calling by value.
> In the following code, I don't gain cosiderable performance with call-
> by-reference vs. call-by-value. Indeed, the perforamnce is absolutely
> unconsiderable:
>

[...]
> void f1(std::vector<int> v)

[...]
> void f2(std::vector<int> v)

[...]
> void f3(std::vector<int>* pv)

[...]

There is no reference. You have two function that do a call-by-value and
one that does a call-by-reference (via pointer).

Obviously, the first two shouldn't show any measurable performance
difference.

--
Thomas
 
Reply With Quote
 
Saeed Amrollahi
Guest
Posts: n/a
 
      07-11-2008
On Jul 11, 9:54*pm, "Thomas J. Gritzan" <(E-Mail Removed)>
wrote:
> Saeed Amrollahi schrieb:> Dear All
> > Hi

>
> > I have learned when an object is big, I should pass the object using a
> > reference or pointer to it rather than calling by value.
> > In the following code, I don't gain cosiderable performance with call-
> > by-reference vs. call-by-value. Indeed, the perforamnce is absolutely
> > unconsiderable:

>
> [...]
> > void f1(std::vector<int> v)

> [...]
> > void f2(std::vector<int> v)

> [...]
> > void f3(std::vector<int>* pv)

>
> [...]
>
> There is no reference. You have two function that do a call-by-value and
> one that does a call-by-reference (via pointer).
>
> Obviously, the first two shouldn't show any measurable performance
> difference.
>
> --
> Thomas


Hi
Sorry for typo and confusion. I actually used reference in the code:
void f1(std::vector<int> v)
void f2(std::vector<int>& v)
void f3(std::vector<int>* pv)

Based on
 
Reply With Quote
 
Saeed Amrollahi
Guest
Posts: n/a
 
      07-11-2008
On Jul 11, 9:54*pm, "Thomas J. Gritzan" <(E-Mail Removed)>
wrote:
> Saeed Amrollahi schrieb:> Dear All
> > Hi

>
> > I have learned when an object is big, I should pass the object using a
> > reference or pointer to it rather than calling by value.
> > In the following code, I don't gain cosiderable performance with call-
> > by-reference vs. call-by-value. Indeed, the perforamnce is absolutely
> > unconsiderable:

>
> [...]
> > void f1(std::vector<int> v)

> [...]
> > void f2(std::vector<int> v)

> [...]
> > void f3(std::vector<int>* pv)

>
> [...]
>
> There is no reference. You have two function that do a call-by-value and
> one that does a call-by-reference (via pointer).
>
> Obviously, the first two shouldn't show any measurable performance
> difference.
>
> --
> Thomas



Hi
Sorry for typo and confusion. I actually used reference in the code:
void f1(std::vector<int> v)
void f2(std::vector<int>& v)
void f3(std::vector<int>* pv)

Based on guys' advice, I changed my simple benckmark code to better
one:

template<class T>
void f1(std::vector<T> v)
{
for (int sz = 0; sz < 1000000; sz++)
v.push_back(T());
}

template<class T>
void f2(std::vector<T>& v)
{
for (int sz = 0; sz < 1000000; sz++)
v.push_back(T());
}

template<class T>
void f3(std::vector<T>* pv)
{
for (int sz = 0; sz < 1000000; sz++)
pv->push_back(T());

}

int main()
{

vector<int> v; // empty vector

cout << "f1 called" << '\n';
for (int i = 0; i < 10; i++) {
vector<int> v;
f1(v);
}
cout << "f1 end" << '\n';
v.clear();
cout << "f2 called" << '\n';
for (int i = 0; i < 10; i++) {
vector<int> v;
f2(v);
}
cout << "f2 end" << '\n';
v.clear();
cout << "f3 called" << '\n';
for (int i = 0; i < 10; i++) {
vector<int> v;
f3(&v);
}
cout << "f3 end" << '\n';
v.clear();

return 0;
}

I don't use a precise clock, but I expected a difference order of
magnitude efficiency but it is not.
I tested with vector<int>, vector<double> and vector<string>.


Regards,
Saeed
 
Reply With Quote
 
Erik Wikström
Guest
Posts: n/a
 
      07-11-2008
On 2008-07-11 21:44, Saeed Amrollahi wrote:
> On Jul 11, 9:54 pm, "Thomas J. Gritzan" <(E-Mail Removed)>
> wrote:
>> Saeed Amrollahi schrieb:> Dear All
>> > Hi

>>
>> > I have learned when an object is big, I should pass the object using a
>> > reference or pointer to it rather than calling by value.
>> > In the following code, I don't gain cosiderable performance with call-
>> > by-reference vs. call-by-value. Indeed, the perforamnce is absolutely
>> > unconsiderable:

>>
>> [...]
>> > void f1(std::vector<int> v)

>> [...]
>> > void f2(std::vector<int> v)

>> [...]
>> > void f3(std::vector<int>* pv)

>>
>> [...]
>>
>> There is no reference. You have two function that do a call-by-value and
>> one that does a call-by-reference (via pointer).
>>
>> Obviously, the first two shouldn't show any measurable performance
>> difference.
>>
>> --
>> Thomas

>
>
> Hi
> Sorry for typo and confusion. I actually used reference in the code:
> void f1(std::vector<int> v)
> void f2(std::vector<int>& v)
> void f3(std::vector<int>* pv)
>
> Based on guys' advice, I changed my simple benckmark code to better
> one:
>
> template<class T>
> void f1(std::vector<T> v)
> {
> for (int sz = 0; sz < 1000000; sz++)
> v.push_back(T());
> }
>
> template<class T>
> void f2(std::vector<T>& v)
> {
> for (int sz = 0; sz < 1000000; sz++)
> v.push_back(T());
> }
>
> template<class T>
> void f3(std::vector<T>* pv)
> {
> for (int sz = 0; sz < 1000000; sz++)
> pv->push_back(T());
>
> }
>
> int main()
> {
>
> vector<int> v; // empty vector
>
> cout << "f1 called" << '\n';
> for (int i = 0; i < 10; i++) {
> vector<int> v;
> f1(v);
> }
> cout << "f1 end" << '\n';
> v.clear();
> cout << "f2 called" << '\n';
> for (int i = 0; i < 10; i++) {
> vector<int> v;
> f2(v);
> }
> cout << "f2 end" << '\n';
> v.clear();
> cout << "f3 called" << '\n';
> for (int i = 0; i < 10; i++) {
> vector<int> v;
> f3(&v);
> }
> cout << "f3 end" << '\n';
> v.clear();
>
> return 0;
> }
>
> I don't use a precise clock, but I expected a difference order of
> magnitude efficiency but it is not.
> I tested with vector<int>, vector<double> and vector<string>.


Make sure you measure the right thing:

#include <iostream>
#include <vector>

size_t f1(std::vector<int> v)
{
return v.size();
}

size_t f2(const std::vector<int>& v)
{
return v.size();
}

size_t f3(std::vector<int>* v)
{
return v->size();
}

int main()
{

std::vector<int> v(1000000); // empty vector
std::cout << "Start" << std::endl;

for (int i = 0; i < 1000; ++i)
f1(v);
std::cout << "f1 done" << std::endl;

for (int i = 0; i < 1000; ++i)
f2(v);
std::cout << "f2 done" << std::endl;

for (int i = 0; i < 1000; ++i)
f3(&v);
std::cout << "f3 done" << std::endl;

return 0;
}

This shows the overhead of passing a vector with 10^6 elements by value
instead of by pointer/reference. If you want to be sure you can
rearrange the calls so that f1() is called in second or third and see
what takes the longest.

--
Erik Wikström
 
Reply With Quote
 
Saeed Amrollahi
Guest
Posts: n/a
 
      07-12-2008
On Jul 11, 11:06*pm, Erik Wikstrm <(E-Mail Removed)> wrote:
> On 2008-07-11 21:44, Saeed Amrollahi wrote:
>
>
>
>
>
> > On Jul 11, 9:54 pm, "Thomas J. Gritzan" <(E-Mail Removed)>
> > wrote:
> >> Saeed Amrollahi schrieb:> Dear All
> >> > Hi

>
> >> > I have learned when an object is big, I should pass the object using a
> >> > reference or pointer to it rather than calling by value.
> >> > In the following code, I don't gain cosiderable performance with call-
> >> > by-reference vs. call-by-value. Indeed, the perforamnce is absolutely
> >> > unconsiderable:

>
> >> [...]
> >> > void f1(std::vector<int> v)
> >> [...]
> >> > void f2(std::vector<int> v)
> >> [...]
> >> > void f3(std::vector<int>* pv)

>
> >> [...]

>
> >> There is no reference. You have two function that do a call-by-value and
> >> one that does a call-by-reference (via pointer).

>
> >> Obviously, the first two shouldn't show any measurable performance
> >> difference.

>
> >> --
> >> Thomas

>
> > Hi
> > Sorry for typo and confusion. I actually used reference in the code:
> > void f1(std::vector<int> v)
> > void f2(std::vector<int>& v)
> > void f3(std::vector<int>* pv)

>
> > Based on guys' advice, I changed my simple benckmark code to better
> > one:

>
> > template<class T>
> > void f1(std::vector<T> v)
> > {
> > * *for (int sz = 0; sz < 1000000; sz++)
> > * * * * * *v.push_back(T());
> > }

>
> > template<class T>
> > void f2(std::vector<T>& v)
> > {
> > * *for (int sz = 0; sz < 1000000; sz++)
> > * * * * * *v.push_back(T());
> > }

>
> > template<class T>
> > void f3(std::vector<T>* pv)
> > {
> > * *for (int sz = 0; sz < 1000000; sz++)
> > * * * * * *pv->push_back(T());

>
> > }

>
> > int main()
> > {

>
> > * *vector<int> v; // empty vector

>
> > * *cout << "f1 called" << '\n';
> > * *for (int i = 0; i < 10; i++) {
> > * * * * * *vector<int> v;
> > * * * * * *f1(v);
> > * *}
> > * *cout << "f1 end" << '\n';
> > * *v.clear();
> > * *cout << "f2 called" << '\n';
> > * *for (int i = 0; i < 10; i++) {
> > * * * * * *vector<int> v;
> > * * * * * *f2(v);
> > * *}
> > * *cout << "f2 end" << '\n';
> > * *v.clear();
> > * *cout << "f3 called" << '\n';
> > * *for (int i = 0; i < 10; i++) {
> > * * * * * *vector<int> v;
> > * * * * * *f3(&v);
> > * *}
> > * *cout << "f3 end" << '\n';
> > * * * * v.clear();

>
> > * *return 0;
> > }

>
> > I don't use a precise clock, but I expected a difference order of
> > magnitude efficiency but it is not.
> > I tested with vector<int>, vector<double> and vector<string>.

>
> Make sure you measure the right thing:
>
> #include <iostream>
> #include <vector>
>
> size_t f1(std::vector<int> v)
> {
> * * return v.size();
>
> }
>
> size_t f2(const std::vector<int>& v)
> {
> * * return v.size();
>
> }
>
> size_t f3(std::vector<int>* v)
> {
> * * return v->size();
>
> }
>
> int main()
> {
>
> * * std::vector<int> v(1000000); // empty vector
> * * std::cout << "Start" << std::endl;
>
> * * for (int i = 0; i < 1000; ++i)
> * * * * f1(v);
> * * std::cout << "f1 done" << std::endl;
>
> * * for (int i = 0; i < 1000; ++i)
> * * * * f2(v);
> * * std::cout << "f2 done" << std::endl;
>
> * * for (int i = 0; i < 1000; ++i)
> * * * * f3(&v);
> * * std::cout << "f3 done" << std::endl;
>
> * * return 0;
>
> }
>
> This shows the overhead of passing a vector with 10^6 elements by value
> instead of by pointer/reference. If you want to be sure you can
> rearrange the calls so that f1() is called in second or third and see
> what takes the longest.
>
> --
> Erik Wikstrm- Hide quoted text -
>
> - Show quoted text -


Hi
I ran your program and I do see the big difference. I really don't
know why my benchmark doesn't work.
I should review my code. Erik, Thomas, Ali, Juha, Soumen and Ron thank
you.

---
Saeed Amrollahi
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
C : Call by value or reference Nehil C Programming 24 07-16-2007 08:30 AM
difference b/w call by reference and call by pointer ravi C Programming 10 02-23-2007 10:57 AM
function call by value and by reference mitchellpal@gmail.com C Programming 13 02-06-2006 09:32 AM
call by value / (const) reference Alexander Stippler C++ 9 01-26-2004 05:50 AM
Passing the value by reference is same as pointer by reference sam pal C++ 3 07-16-2003 09:14 PM



Advertisments