开发者

When returning an object, why put the creation+initialization and the return as two seperate statements instead of one?

开发者 https://www.devze.com 2023-03-10 01:54 出处:网络
Example: Foo make_foo(int a1, 开发者_JAVA百科int a2){ Foo f(a1,a2); return f; } Having seen such functions several times, is it just a matter of coding style / preference or is there more to it tha

Example:

Foo make_foo(int a1, 开发者_JAVA百科int a2){
  Foo f(a1,a2);
  return f;
}

Having seen such functions several times, is it just a matter of coding style / preference or is there more to it than meets the eye? Specifically this answer got me thinking with the make_unique implementation and the claim it is exception safe - is that related to the splitting of creation and return? Or am I reading too much into this? Why not simply write

Foo make_foo(int a1, int a2){
  return Foo(a1,a2);
}


it's perfectly ok to combine creation and return, text books do it on separate lines often to clarify the code somewhat.


Note that the answer to which you refer actually has something different:

std::unique_ptr<T> ret (new T(std::forward<Args>(args)...));

In this line of code, explicit dynamic allocation is performed. Best practices dictate that whenever you perform explicit dynamic allocation, you should immediately assign the result to a named smart pointer. For more details, consult the Boost shared_ptr best practices documentation or Herb Sutter's GotW article, "Exception-Safe Function Calls."

It isn't always dangerous to have a new expression as a subexpression of a larger expression, but it's a rule that is easy to forget, so it's best to always follow the best practices guideline and assign a new dynamically allocated object to a named smart pointer.


That said, there is at least one advantage to the pattern of creating a named object and then returning it: it can be a bit easier to "watch" the object in the debugger when stepping through code quickly.

One possible disadvantage is that it is potentially more difficult for a compiler to perform Return Value Optimization (RVO) with a named object. Named Return Value Optimization (NRVO) is not always as straightforward as RVO with an unnamed temporary. I'd hazard to guess that modern compilers wouldn't have a problem either way, but I am not an expert on C++ compiler optimizations.


It is totally dependent on your requirement and you can put them into single statement.It is done to make the code more readable.

In most of the books and other technical resources there are separate statements for creation ,instantiation and return in the earlier chapters but as you go on reading they are merged into a single statement.


Personally, any time I write a class-template I also write a corresponding make_ function-template to allow for creation of objects of the class-template's type without explicitly specifying the template arguments. Of course, this is generally only when using a compiler with C++0x's auto semantics or when passing a temporary as a function argument, but in my opinion both of these are common enough scenarios to warrant the effort.

That said, I've never written code like this for creation of a non-template type.


Historically, the first version

Foo make_foo(int a1, int a2)
{
    Foo f(a1,a2);
    return f; 
} 

had a better chance of triggering the NRVO optimization in some compilers (like older MSVC).

Version 2 should work just as well for compilers implementing the RVO, but historically it wasn't as reliable.

0

精彩评论

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

关注公众号