Is it evil to return C + + reference variables?

I think it's a bit subjective; I'm not sure it's going to agree (I've seen a lot of code snippets that return references).

According to This problem Commentary I just asked about initializing references , the return reference can be evil because [as far as I know] it's easier to miss deleting it, which can lead to a memory leak.

This worries me, because I follow some examples (unless I imagine things) and have done such things in quite a lot of places... Have I misunderstood? Is this evil? If so, how evil is it?

I think because my pointer and reference are mixed together, plus I'm a novice in C + +, and I'm completely confused about when to use them, my application must be a hell of memory leakage

In addition, I know that using smart / shared pointers is often considered the best way to avoid memory leaks.

#1 building

About terrible Code:

int& getTheValue()
{
   return *new int;
}

Indeed, the memory pointer is missing after returning. But if you use shared ﹐ PTR like this:

int& getTheValue()
{
   std::shared_ptr<int> p(new int);
   return *p->get();
}

Memory will not be lost after return and will be released after allocation.

#2 building

Return references are often used in C + + for o perator overloading of large objects because the return value requires a copy operation. (in a performer overload, we usually don't use a pointer as the return value.)

But return references can cause memory allocation problems. Because a reference to a result passes a function as a reference to a return value, the return value cannot be an automatic variable.

If you want to use return references, you can use the buffer for static objects. 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 can safely use the return reference.

But you can always use pointers instead of references to return values in functiong.

#3 building

I think it's much easier to use a reference as the return value of a function than a pointer. Second, it is always safe to use static variables that are referenced by return values.

#4 building

The best way is to create an object and pass it as a reference / pointer parameter to the function that assigns the variable.

It's not a good idea to allocate objects in a function and return them as references or pointers, which are safer, because memory is freed at the end of the function block.

#5 building

I find the answer is not satisfactory, so I will add two cents.

Let's analyze the following:

Wrong use

int& getInt()
{
    int x = 4;
    return x;
}

This is obviously wrong

int& x = getInt(); // will refer to garbage

For static variables

int& getInt()
{
   static int x = 4;
   return x;
}

This is true, because static variables exist throughout the life cycle of a program.

int& x = getInt(); // valid reference, x = 4

This is also common when implementing the Singleton pattern

Class Singleton
{
    public:
        static Singleton& instance()
        {
            static Singleton instance;
            return instance;
        };

        void printHello()
        {
             printf("Hello");
        };

}

Usage:

 Singleton& my_sing = Singleton::instance(); // Valid Singleton instance
 my_sing.printHello();  // "Hello"

Operator

For example, standard library containers rely heavily on the use of operators that return references

T & operator*();

Can be used below

std::vector<int> x = {1, 2, 3}; // create vector with 3 elements
std::vector<int>::iterator iter = x.begin(); // iterator points to first element (1)
*iter = 2; // modify first element, x = {2, 2, 3} now

Quick access to internal data

Sometimes you can use & to quickly access internal data

Class Container
{
    private:
        std::vector<int> m_data;

    public:
        std::vector<int>& data()
        {
             return m_data;
        }
}

Usage:

Container cont;
cont.data().push_back(1); // appends element to std::vector<int>
cont.data()[0] // 1

But this can lead to traps like this:

Container* cont = new Container;
std::vector<int>& cont_data = cont->data();
cont_data.push_back(1);
delete cont; // This is bad, because we still have a dangling reference to its internal data!
cont_data[0]; // dangling reference!

Added by Plagel on Mon, 16 Mar 2020 11:04:46 +0200