【问题标题】:C++ reference to local temporary objectC++ 对本地临时对象的引用
【发布时间】:2016-02-04 11:02:53
【问题描述】:

考虑下面的模板类

template <typename T>
class A {
public:
    virtual T const& getContent() = 0;
};  

我使用'int*'作为类型'T'派生这个类,如下

class A1 : public A<int*> {
private:
    int a;
public:
    int* const& getContent() { return &a; }
};

我收到以下警告:'返回对本地临时对象的引用'。

问题:

  1. 编译器是否在返回其引用之前从“&a”隐式实例化“int * const”类型的本地临时对象?

  2. 我知道 A.a 确实存在,那么我可以忽略这个警告吗?使用此代码会不会有任何不良副作用?

  3. 处理这种情况的正确方法是什么?我是否需要使用成员变量 'int *a' 来代替。这会很麻烦。

【问题讨论】:

  • T const&amp; getContent() = 0:你是说virtual T const&amp; getContent() = 0吗?
  • getContent 函数也应该声明为 const

标签: c++


【解决方案1】:
  1. 是的。
  2. 您不能忽略此警告。 A.a 存在,但这不是问题。您返回的不是指向int 的指针,而是对指向int 的指针的引用,即它是双重间接。具体来说,在getContent 内部创建了一个临时的int*,它指向A.a。对该临时对象的引用被返回,然后该临时对象被销毁。使用getContent 的结果将是未定义的行为。
  3. 处理这种情况的惯用方法通常是存储您传递 const 引用的成员。换句话说,有一个成员int* a,然后在你的函数中简单地返回a。返回 const 引用是公开数据成员的全部功能的常用方法,而不允许类的用户对其进行变异,从而弄乱类的不变量。

【讨论】:

    【解决方案2】:

    这是不正确的:

    T const& getContent() = 0;
    

    你可以这样做:

    T const getContent() = 0;
    int* const getContent() { return &a; }
    

    【讨论】:

      【解决方案3】:

      首先...

      int* const&
      

      和...一样

      int *const&
      

      编辑:最初,我错误地说它等同于const int*&amp;。对不起,那是我的错。

      而且,对指针的引用比指针本身更“麻烦”(至少恕我直言),你不这么认为吗?指针和引用永远不能混合是有原因的(当然,除非它是模板实例化的连续性)...

      int const&*
      

      这是不可能的,无效的,最后但同样重要的是,疯狂。尽管除了通过指针之外没有其他实用的方法可以实现引用,但它们是 not 对象,因为它们(它们自己)没有不等于它们的 sizeof引用的类型,以及它们根本没有地址的事实,至少就 N4296 的神圣著作而言。

      但是...指针对象!表达式&amp;a 返回一个int* 类型的右值(基本上是一个没有地址的对象)。现在,return &amp;a; 语句将采用该值并将其包装在引用中,因为...

      • 这就是函数返回类型所期望的。
      • T 类型的右值的生命周期可以通过将其保存在const T&amp; 类型的引用中来延长。但是,您不能使用它来返回对临时右值的引用。

      现在,因为所有这些东西都意味着您正在以一种不允许的方式返回对临时右值的引用,所以您受到了诱惑并陷入了未定义的行为。

      解决方案?一开始就不要使用对指针的引用...

      int const *getContent() { return a; }
      

      或者,如果您愿意,可以使用引用,而不是指针...

      int const &getContent() { return *a; }
      

      现在,回答问题!

      • *编译器是否在返回其引用之前从“&a”隐式实例化类型为“int * const”的本地临时对象?*:是和否。它确实实例化了上面解释的这样一个临时对象(但通常会优化掉),但它的类型是 int*,而不是 int *const,尽管后者被隐式转换为前者。
      • 我知道 A.a 确实存在,那么我可以忽略这个警告吗?使用此代码会有任何不良副作用吗?:这取决于您是否会忽略除零警告。
      • 处理这种情况的正确方法是什么?我是否需要使用成员变量 'int *a' 来代替。这会很麻烦。:您可以使用“繁琐”的指针或“漂亮”的引用,见上文。

      我希望这对你有所启发!

      【讨论】:

      • 我 99% 确定 int* const&amp; 不等于 const int*&amp;const 绑定到其左侧的类型标记(除非它是最左侧的标记,否则为方便起见它绑定到右侧)。 const int*&amp; 是对指向 const int 的指针的引用; int* const&amp; 是对指向非const intconst 指针的引用。 const int*&amp;等价于int const *&amp;,但不是int* const&amp;
      • 指针和引用确实总是混入实际代码中,尤其是通用代码。考虑一个向量。在某些情况下非常有用。这种结构的 operator[] 的返回类型是什么?另外,我很好奇您是否是对其他两个答案投了反对票的人;如果是这样,我想知道为什么。
      • 好吧,那将是一个特例:)。我的意思是明确地混合它们。那么最好编辑那部分。顺便说一句,你为什么问我是否对这些问题投了反对票?我不是投反对票的人,我也没有任何理由这样做。
      • @ShadowRanger:对不起,我的错。你是对的,所以我会编辑我的答案。我通常会注意到 const int*int *const 之间的区别,但是引用 + 指针确实搞砸了我的心理类型解析。
      • 我的错,只是几乎在您回答的同时,两者都被否决了。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-14
      • 1970-01-01
      相关资源
      最近更新 更多