Is the practice of returning a C++ reference varia

2019-01-01 12:00发布

This is a little subjective I think; I'm not sure if the opinion will be unanimous (I've seen a lot of code snippets where references are returned).

According to a comment toward this question I just asked, regarding initializing references, returning a reference can be evil because, [as I understand] it makes it easier to miss deleting it, which can lead to memory leaks.

This worries me, as I have followed examples (unless I'm imagining things) and done this in a fair few places... Have I misunderstood? Is it evil? If so, just how evil?

I feel that because of my mixed bag of pointers and references, combined with the fact that I'm new to C++, and total confusion over what to use when, my applications must be memory leak hell...

Also, I understand that using smart/shared pointers is generally accepted as the best way to avoid memory leaks.

16条回答
十年一品温如言
2楼-- · 2019-01-01 12:01

There are two cases:

  • const reference --good idea, sometimes, especially for heavy objects or proxy classes, compiler optimization

  • non-const reference --bad idea, sometimes, breaks encapsulations

Both share same issue -- can potentially point to destroyed object...

I would recommend using smart pointers for many situations where you require to return a reference/pointer.

Also, note the following:

There is a formal rule - the C++ Standard (section 13.3.3.1.4 if you are interested) states that a temporary can only be bound to a const reference - if you try to use a non-const reference the compiler must flag this as an error.

查看更多
看淡一切
3楼-- · 2019-01-01 12:01
    Class Set {
    int *ptr;
    int size;

    public: 
    Set(){
     size =0;
         }

     Set(int size) {
      this->size = size;
      ptr = new int [size];
     }

    int& getPtr(int i) {
     return ptr[i];  // bad practice 
     }
  };

getPtr function can access dynamic memory after deletion or even a null object. Which can cause Bad Access Exceptions. Instead getter and setter should be implemented and size verified before returning.

查看更多
浪荡孟婆
4楼-- · 2019-01-01 12:02

return reference is usually used in operator overloading in C++ for large Object, because returning a value need copy operation.(in perator overloading, we usually don't use pointer as return value)

But return reference may cause memory allocation problem. Because a reference to the result will be passed out of the function as a reference to the return value, the return value cannot be an automatic variable.

if you want use returning refernce, you may use a buffer of static object. for example

const max_tmp=5; 
Obj& get_tmp()
{
 static int buf=0;
 static Obj Buf[max_tmp];
  if(buf==max_tmp) buf=0;
  return Buf[buf++];
}
Obj& operator+(const Obj& o1, const Obj& o1)
{
 Obj& res=get_tmp();
 // +operation
  return res;
 }

in this way, you could use returning reference safely.

But you could always use pointer instead of reference for returning value in functiong.

查看更多
不再属于我。
5楼-- · 2019-01-01 12:07

Best thing is to create object and pass it as reference/pointer parameter to a function which allocates this variable.

Allocating object in function and returning it as a reference or pointer (pointer is safer however) is bad idea because of freeing memory at the end of function block.

查看更多
旧人旧事旧时光
6楼-- · 2019-01-01 12:08

No. No, no, a thousand times no.

What is evil is making a reference to a dynamically allocated object and losing the original pointer. When you new an object you assume an obligation to have a guaranteed delete.

But have a look at, eg, operator<<: that must return a reference, or

cout << "foo" << "bar" << "bletch" << endl ;

won't work.

查看更多
流年柔荑漫光年
7楼-- · 2019-01-01 12:08

Addition to the accepted answer:

struct immutableint {
    immutableint(int i) : i_(i) {}

    const int& get() const { return i_; }
private:
    int i_;
};

I'd argue that this example is not okay and should be avoided if possible. Why? It is very easy to end-up with a dangling reference.

To illustrate the point with an example:

struct Foo
{
    Foo(int i = 42) : boo_(i) {}
    immutableint boo()
    {
        return boo_;
    }  
private:
    immutableint boo_;
};

entering the danger-zone:

Foo foo;
const int& dangling = foo.boo().get(); // dangling reference!
查看更多
登录 后发表回答