【问题标题】:Returning an object confusion返回对象混淆
【发布时间】:2017-01-11 10:25:22
【问题描述】:

我一直在学习 C++,但我无法理解成员函数/方法返回对象的方式。我正在关注“在 21 天内自学 C++”一书。

所以,我了解类和对象,只是不太了解返回对象。我将提供一个示例(目前正在学习运算符重载)。

const Counter& Counter::operator++()
{
    ++itsVal;
    return *this;
}

我只是对返回类型感到很困惑。这个方法说它应该返回一个对计数器对象的引用,但是当对象被取消引用时

return *this;

我们不只是返回一个 Counter 类的对象吗?为什么函数头说我们正在返回对计数器对象的引用?为什么方法头不直接说返回类型是 Counter 类型的对象?这就是我感到困惑的地方:\

我的想法是,由于引用基本上是某事物的别名,因此返回取消引用的指针就像返回对象别名一样,因为对象具有帮助我们识别它们的名称。我真的不知道,我希望这里有人能给我解释一下。

【问题讨论】:

  • 返回“类Couter的对象”将创建副本(第二个实例),这种编程方式的主要思想是对同一对象实例使用点运算符。对不起我的英语,无法解释更多。
  • 同意@Sam Varshavchik ,多点运算符技术是先进的(这种符号是其中的一部分)。通过价值/参考示例学习基础知识。
  • 你确定有const吗?这是非常规且不切实际的,与内置前缀 ++ 不同。
  • 是的,我有这本书的 PDF 版本,并复制了函数定义本身。确实,那里有一个“常量”

标签: c++ return return-type


【解决方案1】:

我们不只是返回一个 Counter 类的对象吗?

是的,我们正在返回一个对象。但是,它是按引用返回还是按值返回,是由函数声明中的返回类型决定的,我们无法在return语句中确定(或区分)它们。

const Counter& Counter::operator++() // return by reference (to const)
{
    ++itsVal;
    return *this;
}

Counter Counter::operator++()        // return by value. Note the body of function is the same.
{
    ++itsVal;
    return *this;
}

顺便说一句:通过引用 const(并且按值,上面的示例仅用于说明)返回前缀 operator++ 没有意义。它实际上应该返回对非常量的引用。比如

Counter& Counter::operator++() // return by reference (to non-const)
{
    ++itsVal;
    return *this;
}

【讨论】:

  • 顺便说一句:通过“在 21 天内自学 C++”来学习 C++ 似乎是个坏主意。
  • @Pistax (1) 这是误导。在 21 天内掌握 C++ 是不可能的。 (2) 请查看here 以获得更好的书籍。
  • @Pistax 是的,这是一本适合初学者的好书。可能比“......在 21 天内”更难,这是值得的。顺便说一句:请参阅我编辑的答案,在这里返回对 const 的引用没有意义。这可能是本书的缺陷之一。
  • 嗯……这就解释了为什么我不理解作者在这里所做的一些事情。非常感谢您指出这些缺陷。我想我得开始写另一本书了。非常感谢您和其他人的帮助:]
  • @Pistax 哦,读那本书似乎更难了。不管怎样,祝你好运,换书后。 :)
【解决方案2】:

我的想法是,由于引用基本上是某事物的别名,因此返回取消引用的指针就像返回对象别名

是的,完全正确。该函数返回调用该函数的对象的别名。它不会复制该对象以返回。

调用代码可能如下所示:

Counter c;
do_something( ++c + 5 );

由于++c 返回了c 的别名,因此这段代码的行为类似于:

++c;
do_something( c + 5 );

不要复制任何不必要的c

【讨论】:

    【解决方案3】:

    返回 *this;

    我们不只是返回一个 Counter 类的对象吗?

    不,这会返回对对象的引用。

    * 运算符是取消引用运算符。此运算符的结果是对指针指向的对象的引用。 this 是一个指针。

    关于引用的事情是,当在非引用上下文中使用时,它们最终会自动“转换”为被引用的对象。

    T *t;
    
    // ...
    
    T u = *t;
    

    正如我所说,* 运算符的结果是一个引用。然后,将结果用于非引用上下文中,即分配给另一个本身不是引用的对象。这最终会解析到引用的对象,从而产生一个副本。

    介绍性 C++ 入门书通常会声明“*p”解析为指针指向的对象。这只是一个善意的小谎言。这仅在非参考上下文中是正确的。这留下了解析到引用的中间步骤,然后解析到被引用对象的引用。

    此时,在典型的 C++ 入门入门中,参考文献尚未作为主题提出。因此,为了避免混淆,省略了这个中间步骤。但既然您对参考有所了解,您需要进行一些心理调整:

    * 为您提供指针指向的对象的引用。在引用上下文中使用时:也就是说,将结果分配给引用,将结果作为参数传递给作为引用的函数,或从函数返回引用,您将获得该引用。在所有其他非引用上下文中,您最终将获得引用所引用的对象,这通常涉及制作对象的副本。

    【讨论】:

    • *t 的结果是T 类型的左值。不是参考(无论是什么意思),当然不是T&。没有“参考上下文”和“非参考上下文”之类的东西。你回答的每一部分都是荒谬和令人困惑的。
    【解决方案4】:

    在对象被itsVal加上1修改后,该方法返回类对象本身。

    您可以使用counter_object++ 自增,然后调用其他函数。如(counter_object++).func(),无需创建另一个对象。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-12-29
      • 1970-01-01
      • 2010-11-30
      • 2012-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多