Created
October 26, 2012 21:53
-
-
Save alexeiz/3961796 to your computer and use it in GitHub Desktop.
Analysis of passing function parameters by-value vs by-reference in C++
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
testing: by value | |
* lvalue | |
lvalue: cctor | |
lvalue: mctor | |
* xvalue | |
xvalue: mctor | |
xvalue: mctor | |
* rvalue | |
rvalue: mctor | |
* done | |
testing: by referece | |
* lvalue | |
lvalue: cctor | |
* xvalue | |
xvalue: mctor | |
* rvalue | |
rvalue: mctor | |
* done | |
testing: by value, no return | |
* lvalue | |
lvalue: cctor | |
* xvalue | |
xvalue: mctor | |
* rvalue | |
* done | |
testing: by referece, no return | |
* lvalue | |
lvalue: cctor | |
* xvalue | |
* rvalue | |
* done | |
testing: by value constructor param | |
* lvalue | |
lvalue: cctor | |
lvalue: mctor | |
* xvalue | |
xvalue: mctor | |
xvalue: mctor | |
* rvalue | |
rvalue: mctor | |
* done | |
testing: by reference constructor param | |
* lvalue | |
lvalue: cctor | |
* xvalue | |
xvalue: mctor | |
* rvalue | |
rvalue: mctor | |
* done |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <utility> | |
using namespace std; | |
struct tracer | |
{ | |
tracer(char const * id) | |
: id_(id) | |
{ | |
// trace("ctor"); | |
} | |
tracer(tracer const & other) | |
: id_(other.id_) | |
{ | |
trace("cctor"); | |
} | |
tracer(tracer && other) | |
: id_(other.id_) | |
{ | |
trace("mctor"); | |
} | |
tracer & operator=(tracer const & other) | |
{ | |
id_ = other.id_; | |
trace("copy-assign"); | |
return *this; | |
} | |
tracer & operator=(tracer && other) | |
{ | |
id_ = other.id_; | |
trace("move-assign"); | |
return *this; | |
} | |
~tracer() | |
{ | |
// trace("dtor"); | |
} | |
void trace(char const * message) | |
{ | |
clog << id_ << ": " << message << endl; | |
} | |
char const * id_; | |
}; | |
void modify(tracer & obj) | |
{ | |
obj.id_ = (char *)(((intptr_t) obj.id_) & ~0x800000000000000ull); | |
} | |
struct by_value_design | |
{ | |
tracer operator()(tracer obj) | |
{ | |
modify(obj); | |
return obj; | |
} | |
}; | |
struct by_value_noret_design | |
{ | |
void operator()(tracer obj) | |
{ | |
modify(obj); | |
} | |
}; | |
struct by_value_constructor | |
{ | |
by_value_constructor(tracer obj) | |
: obj_(move(obj)) | |
{} | |
tracer obj_; | |
}; | |
struct by_ref_design | |
{ | |
tracer operator()(tracer const & obj) | |
{ | |
tracer tmp(obj); | |
modify(tmp); | |
return tmp; | |
} | |
tracer operator()(tracer && obj) | |
{ | |
modify(obj); | |
return move(obj); | |
} | |
}; | |
struct by_ref_noret_design | |
{ | |
void operator()(tracer const & obj) | |
{ | |
tracer tmp(obj); | |
modify(tmp); | |
} | |
void operator()(tracer && obj) | |
{ | |
modify(obj); | |
} | |
}; | |
struct by_ref_constructor | |
{ | |
by_ref_constructor(tracer const & obj) | |
: obj_(obj) | |
{} | |
by_ref_constructor(tracer && obj) | |
: obj_(move(obj)) | |
{} | |
tracer obj_; | |
}; | |
template <typename Design> | |
void test(Design func, char const * desc) | |
{ | |
clog << "testing: " << desc << endl; | |
clog << "* lvalue\n"; | |
tracer lval{"lvalue"}; | |
tracer lval_ret{func(lval)}; | |
clog << "* xvalue\n"; | |
tracer xval{"xvalue"}; | |
tracer xval_ret{func(move(xval))}; | |
clog << "* rvalue\n"; | |
tracer rval_ret{func(tracer("rvalue"))}; | |
clog << "* done\n\n"; | |
} | |
template <typename Design> | |
void test_noret(Design func, char const * desc) | |
{ | |
clog << "testing: " << desc << endl; | |
clog << "* lvalue\n"; | |
tracer lval{"lvalue"}; | |
func(lval); | |
clog << "* xvalue\n"; | |
tracer xval{"xvalue"}; | |
func(move(xval)); | |
clog << "* rvalue\n"; | |
func(tracer("rvalue")); | |
clog << "* done\n\n"; | |
} | |
template <typename Design> | |
void test_constructor(char const * desc) | |
{ | |
clog << "testing: " << desc << endl; | |
clog << "* lvalue\n"; | |
tracer lval{"lvalue"}; | |
Design lval_obj(lval); | |
clog << "* xvalue\n"; | |
tracer xval{"xvalue"}; | |
Design xval_obj(move(xval)); | |
clog << "* rvalue\n"; | |
Design rval_obj(tracer("rvalue")); | |
clog << "* done\n\n"; | |
} | |
int main() | |
{ | |
test(by_value_design(), "by value"); | |
test(by_ref_design(), "by referece"); | |
test_noret(by_value_noret_design(), "by value, no return"); | |
test_noret(by_ref_noret_design(), "by referece, no return"); | |
test_constructor<by_value_constructor>("by value constructor param"); | |
test_constructor<by_ref_constructor>("by reference constructor param"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment