Type and efficiency of C ++ parameter

Based on what I have compiled from the authors of the compiler, value types are much preferable to references / pointers in terms of efficiency.

This is due to the fact that value types are easier to talk about when you do not need to care about an alias, externally modified memory (to which the pointer belongs), the cost of dereferencing a pointer, etc. I must say that although I understand such problems, I still have a few questions regarding specific cases.

Case No. 0

void foo(const float& f) Well, we have a link here, but it is permanent! Of course, we have a constant representation (ref), so outwardly it can be a change, but it can only happen in a multi-threaded world, and I'm not sure that the compiler should take this into account at all if synchronization primitives are not used. Obviously, if inside we used another pointer / reference to any float variable, we could risk changing the f parameter. Can the compiler consider this parameter safe (unless we use ref / ptr to float inside)?

Case No. 1

void foo(vector<int> f) Speaking from the point of view of a C ++ 11/14 programmer, I know that vector can be safely moved to a function. As we all know, inside the container contains a pointer to an array. Will the compiler consider the pointer as safe (without external modifications), since we just received a copy of the vector, so we are its sole owners?

In other words: it is a copied object that is considered safe (since we logically create a clone of the object), or the compiler is not allowed to make such assumptions and any ptr / ref member should be considered as potentially dangerous, since the ctor / op copy may not have done the right thing a copy. Should a programmer not be responsible for processing shared resources when copying them?

Bottomline

Permanent pointers / links and copied complex objects are generally slower than copies of primitives, and therefore should be avoided as much as possible in critical critical code; or are they a little less effective and we don’t have to worry about that?

+4
source share
3 answers

As general rules in modern C ++:

  • For (primitives to copy) primitive types, such as int , float or double , etc., if it is an input parameter (read-only), simply pass the value :

     inline double Square(double x) { return x*x; } 
  • Instead, if the input parameter type is not cheap to copy, but it is cheap to move, for example. std::vector , std::string , etc., consider two subranges:

    a. If the function simply watches the value, then pass a const reference (this will prevent useless potentially expensive deep copies):

     double Average(const std::vector<double> & v) { .... // compute average of elements in v (which is read-only) } 

    b. If the function accepts a local copy of the parameter, then pass by value and std::move from the value (this will optimize due to the semantics of movement):

     void Person::SetName(std::string name) { m_name = std::move(name); } 
+3
source

(It starts as a comment, but it does not fit.)

Case No. 0 has already been discussed before death , for example:

Is it counterproductive to pass primitive types by reference?

which is already a duplicate of the other two questions. In particular, I find this answer a good answer to your case number 0. Related questions:

Question number 1 is not clear to me: Do you need a copy or do you want to move? There is a huge difference between the two, and it is not clear from what you are writing what you need.

If the link is enough, but you are making a copy instead, you are wasting resources.

If you need to make a deep copy, then all that she needs will not help either the link or the move.

Read this answer and go to Case No. 1.

+2
source

Case No. 0

No. It can be changed externally:

 void foo(const float& f) { ..use f.. ..call a function which is not pure.. ..use (and reload) f.. } 

Case # 1 ... Will the compiler consider the pointer safe (without external changes), since we just got a copy of the vector, so we are its sole owners?

No - he should be pessimistic. It can be taught to rely on implementation, but on the whole there is no reasonable way to track this pointer through all possible construction scenarios for an arbitrary design in order to verify that it is safe, even if the implementations were visible.

Bottomline:

The cost of placing and copying containers is usually much more than the cost of downloads and stores - it depends on your program, equipment and implementation!

Passing small objects and embedded links by reference does not mean that the optimizer should consider this as a link when the implementation is visible. For instance. If he sees that the caller is passing a constant, she has the right to do the optimization based on a known constant value. Conversely, creating a copy can interfere with optimizing your program, as complexity can increase. Fretting about whether to pass this trivial / small type by value is an old micro-optimization. Copying a string or an OTOH (not SSO) vector can be huge in comparison. Focus on semantics first.

I write tons of critical performance code and pass almost everything by reference (respectively const-qualified), including built-in ones. You calculate the instructions and memory speed at this point (for your parameters), which is very small on desktop and laptop computers. I tested many times on desktops and laptops before settling this. I do this for consistency - you don’t need to worry about the cost of introducing a link (where there is overhead) outside the built-in. Again, the cost of creating unnecessary copies and any necessary dynamic allocations are usually much higher. Also think that objects have additional functions to build, copy, and destroy for execution - even innocent types can cost much more than copy than reference.

+1
source

Source: https://habr.com/ru/post/1494667/


All Articles