【问题标题】:Why max (max(a,b), c) is error为什么 max (max(a,b), c) 是错误的
【发布时间】:2013-02-21 21:37:43
【问题描述】:

参考:C++ 模板中的代码 sn-p:完整指南

// maximum of two values of any type (call-by-reference) 
template <typename T> 
inline T const& max (T const& a, T const& b) 
{ 
    return a < b ? b : a; 
} 

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

// maximum of three values of any type (call-by-reference) 
template <typename T> 
inline 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 () 
{ 
    ::max(7, 42, 68); // OK 

    const char* s1 = "frederic"; 
    const char* s2 = "anica"; 
    const char* s3 = "lucas"; 
    ::max(s1, s2, s3); // ERROR 

} 

上述代码的问题:

问题是如果你为三个 C 字符串调用 max(), 声明

返回最大值 (max(a,b), c);变成一个错误。这是因为对于 C-strings, max(a,b) 创建一个新的临时本地值,它可能是 由函数通过引用返回。

问题> 我还是不明白以上几点。为什么

"你不能使用三参数版本来计算最大值 三个 C 字符串”?

// 更新

const int* fReturnValue(const int *i)
{
    return i;
}

int main()
{
    int i = 3;
    const int* i4= fReturnValue(&i);

    cout << &i << endl;
    cout << i4 << endl;
}

观察:两行返回相同的地址。 所以我假设在函数 fReturnValue 中,函数按值返回,但它不会伤害 b/c,它是一个指针地址。也就是说,返回地址仍然有效。

这是真的吗?

【问题讨论】:

  • 据我所知,strcmp 不是 std 命名空间的一部分...
  • @thang:是的,是的。
  • cstring 是包含文件吗?哪个 c++ 标准?
  • @thang: cstring 是一个包含文件,当然,任何 C++ 标准。从 C 标准库继承的所有类型和函数都存在于全局命名空间和 std 命名空间中。

标签: c++


【解决方案1】:

问题在于max 的C 字符串 风格按值返回,而不是按值获取参数。通用的 3 路 max 函数被声明为返回一个引用,但 C 字符串 max 返回一个值,这将导致返回一个对之前将死的临时的引用你可以访问它。

更新:您添加的新代码不等同于您原来的问题。这将:

const int*& fReturnValue(const int *i)
{
    return i;
}

请注意,fReturnValue 返回对局部变量 i 的引用,其生命周期在函数返回时结束。因此该函数返回对无效对象的引用。尝试使用该更改编译您的代码,您应该会收到几乎每个编译器的警告。

【讨论】:

  • 为什么按值返回?它按值返回地址。那是什么问题? inline char const* max (char const* a, char const* b) 返回传入变量的地址。
  • @q0987:它按值返回,因为它声明了这样做。然后,通用的 3 路 max 将尝试返回对持有地址的临时指针的引用,所述临时指针将在 max 返回时失效(指针,而不是其中的地址)。
  • @q0987: 问题是它返回一个对不再存在的指针的引用。其实和int*&amp; f(){ int* ptr = 0; return ptr; }没有什么区别@
  • @q0987:将其更改为const int*&amp; fReturnValue(const int *i){ return i; },您将获得与原始代码相同的行为,即返回对已经失效的临时指针的引用。请注意,我现在一直提到问题在于返回对指向地址的无效指针的引用。地址没有问题,它仍然有效,对临时指针的引用很好地保存了该地址......这是另一个故事......试试看,你的编译器应该发出一个_“返回临时引用”警告。
  • 非常感谢您的大力帮助。现在我想我明白你的想法了。基本上fReturnValue中的变量i是局部变量,返回对局部变量的引用是错误的!
猜你喜欢
  • 2017-02-23
  • 1970-01-01
  • 1970-01-01
  • 2018-03-06
  • 2011-05-13
  • 1970-01-01
  • 2020-12-07
  • 2014-03-29
  • 2016-10-31
相关资源
最近更新 更多