开发者

Some confusions this tip about determining passing method of parameters to a function brings up for me

Here's a tip that makes some confusions for me:"to have the best passing method pass built-in types by value and other types by reference to constant" now I have some questions below:

1-first of all I think the reason behind suggesting passing by reference to constant is that if the referenced object is not volatile the compiler can convert it to pass by value if it would be more efficient but it would have made more sense to me if there was a special syntax by which we could tell the comp开发者_JS百科iler ok here determine the best passing method yourself I don't care how it will be but changing pass by reference to constant to pass by value by compiler seems messy somehow to me, in the way it is now if we want the compiler to obey the pass by reference to constant and use a pointer we have to force it to do so since it may determine the more efficient way is to pass by value; so can you lighten me up why it is this way that this is?.

2-Does "pass built-in types by value" include built-in types that are bigger in size than size of a pointer like long double on my platform that has 8 bytes comparing to pointer size that is 4 bytes and does "pass non-built-in types by reference to constant" include things like below that likely can be transfered in memory like built-in types:

struct Test1{
 public:
  char characters[2];
};
struct Test2{
 public:
  char characters[4];
};


a special syntax by which we could tell the compiler ok here determine the best passing method yourself

Boost provides this, as boost::call_traits<T>::param_type.

why it is this way that this is

Probably because the rule of thumb works most of the time. If in doubt, you can pass by const reference and it's unlikely to be horribly inefficient.

In fact there's more to the general tip than you say - "small" types which aren't built-in are also usually best passed by value. For example, the standard library consistently passes iterators by value.

Does "pass built-in types by value" include built-in types that are bigger in size than size of a pointer

Yes. You can reasonably expect a C++ implementation to pass a double or long double by value with acceptable efficiency for almost all practical purposes. If you've reached the stage of optimization where this is the lowest-hanging fruit, then you're beyond general tips. You would measure both in your actual program.

if the referenced object is not volatile the compiler can convert it to pass by value if it would be more efficient

Maybe. If the call is successfully inlined, then the compiler can do pretty much anything. If the call target isn't available to the compiler, then it can't do it, because in practice a change between value vs. const reference parameter requires changes to both the caller and the callee code. Furthermore, aliasing means that unless the compiler has a lot of information about what's going on, then even with a non-volatile object it can't necessarily assume that it won't change:

int foo(const int &a, int &b) {
    b = 2;
    return a;
}

Unless it's inlined, this code cannot be changed to pass a by value, because someone might call it like this:

int a = 1;
std::cout << foo(a,a);

which must print "2", whereas with a passed by value it would print "1".


Re "in the way it is now if we want the compiler to obey the pass by reference to constant and use a pointer we have to force it to do so since it may determine the more efficient way is to pass by value"

No, a compiler can only replace pass-by-ref-to-const with pass-by-value if it can prove that there will be no aliasing (e.g. f calling g which happens to use a pointer to original actual argument to change that argument's value underfoot, so to speak). Generally there will be no problematic aliasing. But proving it is generally difficult.

The upshot is that where you pass by reference, the argument will really be passed by reference unless the call is inlined. And where the compiler does change pass-by-ref-to-const to pass-by-value, if that should happen, then it's where the compiler has proved that nothing is done that could be affected. So you're safe.

Cheers & hth.,


  1. The compiler would likely optimize the parameter passing as it feels best. I don't know in this specific example, but generally speaking, the compiler makes all sorts of front-end and back-end optimizations at each step. So, I don't think you'd need to pass any "special syntax" to the compiler.

  2. Yes, pass-by-value means just that even if the primitive/built-in data type were larger than a memory pointer or register. On 32-bit architectures, doubles (64 bits/8 bytes) and long doubles (80 bits/10 bytes) occupy multiple registers.


Does "pass built-in types by value" include built-in types that are bigger in size than size of a pointer like long double on my platform that has 8 bytes comparing to pointer size that is 4 bytes.

Yes, because those can usually passed in a register which is as efficient as it gets. The only time when passing by const reference might be faster is when you pass something that is already stored in a variable. (But then you pay the extra cost of dereferencing in the callee). Most of the times though, the caller's arguments are arbitrary expressions like a * b + c, and it would be inefficient to first store the result in memory and then pass it indirectly via reference to const.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜