In overloaded set of functions, there is a call that supposedly creates a hanging reference but I don't see that!

Hi,

Supposedly there is an error in the last call to ::max() in the code below, something about returning a temporary local value but I only see returning a pointer by value which is not temporary... I see a call to the 3 parameter ::max function with the parameters passed by reference, then this function calls the 2 parameter ::max that receives pointers to char by value, supposedly creating a temporary local value that is destroyed and leaves a hanging reference. I don't see that. Does somebody see a problem with this set of overloaded functions when called with pointers to char?



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// maximum of two values of any type (call-by-reference)
template<typename T>
T const& max (T const& a, T const& b)
{
  return  b < a ? a : b;
}

// maximum of two C-strings (call-by-value)
char const* max (char const* a, char const* b)
{
  return  std::strcmp(b,a) < 0  ? a : b;
}

// maximum of three values of any type (call-by-reference)
template<typename T>
T const& max (T const& a, T const& b, T const& c)
{
  return max (max(a,b), c);       // error if max(a,b) uses call-by-value
}

int main ()
{
  auto m1 = ::max(7, 42, 68);     // OK

  char const* s1 = "frederic";
  char const* s2 = "anica";
  char const* s3 = "lucas";
  auto m2 = ::max(s1, s2, s3);    // run-time ERROR -- don't see it??
}



Regards,
Juan Dent
Last edited on
First step, in my opinion, would be to remove the templates, because that just adds a layer of complexity to the actual problem.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <cstdlib>
#include <cstring>

char const* max (char const* a, char const* b)
{
  return  std::strcmp(b,a) < 0  ? a : b;
}

char const* const& max (char const*  const& a, char const*  const& b, char const*  const& c)
{
  char const* max_ret = max(a,b);
  return max (max_ret, c);       // error if max(a,b) uses call-by-value
}

int main ()
{
  char const* s1 = "frederic";
  char const* s2 = "anica";
  char const* s3 = "lucas";
  ::max(s1, s2, s3); // run-time ERROR -- don't see it??
}


It's potentially returning that local value -- max_ret -- by reference.
That is what appears to be the issue to me, but hopefully someone else can confirm.

Edit: Fixed copypaste error

Edit 2: You get similar warning if you do:
1
2
3
4
5
char const* const& max (char const*  const& a, char const*  const& b, char const*  const& c)
{
  char const* max_ret = max(a,b);
  return max_ret;
}
Last edited on
but copy elision guarantees that the return value will be copied (or actually pasted) directly into m2 before the temporary expires, right?
The point is that the return value is a reference, which is a synonym for another object. In this case there's a chance that the other object will go out of scope when the function returns.
max_ret is destroyed when control leaves the function's scope.
1
2
// f() always returns a dangling reference
int& f() { int x = 0; return x; }


but copy elision guarantees that the return value will be copied (or actually pasted) directly into m2 before the temporary expires, right?

The variant of copy elision that applies when saying return local_variable is called Named Return Value Optimization, or NRVO. It only occurs when the function's return type and local_variable are the same class type (it is a reference type in the OP), ignoring const and volatile.
Last edited on
Topic archived. No new replies allowed.