繁体   English   中英

悬空指针/对int和char *常量的引用

[英]Dangling pointers/references to int and char* constants

我正在阅读Vandevoorde,Josuttis和Gregor撰写的有关C ++模板的书,但不理解它们对悬挂参考提出的警告。 这是代码:

#include <cstring>

// 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
}

给定的消息是,对于C字符串,嵌套的max(a,b)创建了一个悬空引用,而对于int,则没有。 那么,与char相比,与int的引用相比,char的指针有什么特别之处,因为二者均实现为指向max函数外部分配的对象的指针?

这个:

   char const* max (char const* a, char const* b)

返回一个无名的临时指针值,然后返回:

    return max (max(a,b), c);

返回对其的引用。

...不理解他们对悬挂参考的警告

::max(s1, s2, s3)使用template<typename T> T const& max (T const& a, T const& b, T const& c)返回参考

如果template<typename T> T const& max (T const& a, T const& b, T const& c)的定义更改为:

template<typename T>
T const& max (T const& a, T const& b, T const& c)
{
  return (a > b) ? ((a > c) ? a : c)
                 : ((b > c) ? b : c);
}

没问题,因为它已经有了引用。

但是对于::max(s1, s2, s3) Tconst char*因此在max (max(a,b), c) maxchar const* max (char const* a, char const* b) ,但不是返回引用,因为编译器将char const* max (char const* a, char const* b)的结果保存在堆栈上的临时变量中,并返回对该临时变量的引用,从而生成消息和相关的问题。 就像您做int & f() { int v = 0; return v; } int & f() { int v = 0; return v; } int & f() { int v = 0; return v; }除了临时变量是由编译器本身产生的。

当然,使用template<typename T> T const max (T const& a, T const& b, T const& c) (返回值而不是引用)时问题就消失template<typename T> T const max (T const& a, T const& b, T const& c)因为char const* max (char const* a, char const* b)可以直接返回。

注意::max(7, 42, 68)没问题,因为max max (max(a,b), c)中的max (max(a,b), c)template<typename T> T const& max (T const& a, T const& b)返回参考。

在其他情况下,要继续返回引用,您可以将max专门用于char * ,例如:

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

或定义为

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

其返回引用的版本可以使用具有三个参数的版本,而不必使用临时变量并返回对其的引用。

(我个人更喜欢专业化,因为拥有模板版本看起来很自然)


#include <cstring>
#include <iostream>

// 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;
}

// MODIFIED
// maximum of two C-strings (call-by-value)
template<>
char const* const & max (char const* const & a, char const* 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

  std::cout << m2 << std::endl; // << ADDED TO CHECK
}

编译执行:

pi@raspberrypi:/tmp $ g++ -pedantic -Wall -Wextra s.cc
s.cc: In function ‘int main()’:
s.cc:28:8: warning: unused variable ‘m1’ [-Wunused-variable]
   auto m1 = ::max(7, 42, 68);     // OK
        ^~
pi@raspberrypi:/tmp $ ./a.out
lucas

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM