Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Warning C4172: Returning a reference to const std::string bound to a local variable. How safe is it?

I was just building one of our projects at work and I see a new function was added:

const std::string& ClassName::MethodName() const
{
   return "";
}

The compiler gives a warning:

Warning C4172: returning address of local variable or temporary

I think the compiler is right. How safe is this function?

Note that the function doesn't return const char* which would be OK inasmuch as string literals have static storage duration. It returns a reference to const std::string

like image 970
Armen Tsirunyan Avatar asked Aug 12 '11 11:08

Armen Tsirunyan


4 Answers

Yes it is not safe.
Returning address of a local variable or temporary and dereferencing it results in Undefined Behavior.

As you commented:
Yes, the lifetime of the temporary bound to a constant reference increases till the lifetime of constant. But that needs the caller to accept the return value in a const reference, So by itself the function won't be safe.

From the C++ Standard:
C++03 12.2 Temporary objects:

The second context is when a reference is bound to a temporary. The temporary to which the reference is bound or the temporary that is the complete object to a subobject of which the temporary is bound persists for the lifetime of the reference except as specified below...

A temporary bound to a reference member in a constructor’s ctor-initializer (12.6.2) persists until the constructor exits. A temporary bound to a reference parameter in a function call (5.2.2) persists until the completion of the full expression containing the call.A temporary bound to the returned value in a function return statement (6.6.3) persists until the function exits

like image 55
Alok Save Avatar answered Nov 18 '22 23:11

Alok Save


This is an example that made things clear for me:

#include <iostream>
using std::cout;
struct A{
   A()   {
      cout << "Ctor\n";
   }
   ~A()   {
      cout << "Dtor\n";
   }
};

const A& f(){
   return A();
}

int main(){
   const A& ref = f();
   cout << "1\n";
   {
      const A& ref1 = A();
      cout << "2\n";
   }
   cout << "3\n";
}

Outputs

Ctor
Dtor
1
Ctor
2
Dtor
3
like image 22
Armen Tsirunyan Avatar answered Nov 19 '22 00:11

Armen Tsirunyan


Doing what you did actually does this internally in the compiler:

const std::string* ClassName::MethodName() const
{
   std::string temp = "";
   return &temp;
}

And returning references or pointers to local variables is bad.

like image 3
Dani Avatar answered Nov 19 '22 00:11

Dani


There are circumstances when this code is safe. See GotW #88: A Candidate For the “Most Important const”.

like image 3
user1585719 Avatar answered Nov 19 '22 01:11

user1585719