Skip to content

Instantly share code, notes, and snippets.

@alexeiz
Created October 26, 2012 21:53
Show Gist options
  • Save alexeiz/3961796 to your computer and use it in GitHub Desktop.
Save alexeiz/3961796 to your computer and use it in GitHub Desktop.
Analysis of passing function parameters by-value vs by-reference in C++
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
#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