【问题标题】:Three questions regarding implementing class objects关于实现类对象的三个问题
【发布时间】:2019-04-05 03:11:20
【问题描述】:

问题:

  1. 我使用 cppreference.com 上描述的模板来指导我实现一些功能,例如 push() (在我的例子中是enqueue() )。在 cppreference.com 上,给出了以下模板:

     (a) push(const value_type & value);
     (b) push(value_type && value);
    

https://en.cppreference.com/w/cpp/container/queue/push

由于 (a) 需要引用,文字是如何添加到队列中的?

另外,如果我实现一个函数

         enqueue(Queue const & other) 

使用函数

         enqueue(T const & value) 

通过迭代“其他”并将每个值排入“其他”中,这不会添加“其他”中值的“深层”副本吗?因此,我不应该传递对其他的引用,而是传递一个副本?

  1. 另外,“&&”是什么意思?

  2. 这两个功能如何

     (a) const T & front() const
     (b) T & front()
    

由编译器区分?此外,(a) 在函数名后有一个 const 意味着外部用户将无法修改前面的变量?您甚至想修改队列的前端(或结束)变量吗?

感谢您的宝贵时间!

【问题讨论】:

  • 问题最好是每个问题一个问题。 1 和 2 适合在这里问,甚至在同一个问题中,3 到 6 更适合Code Review。是的,我确实故意链接到“如何提问”帮助页面。
  • 这就是说你所拥有的东西看起来不错。我不会在队列上实现随机访问[] 运算符。队列只允许在一端插入并从另一端提取,因此随机访问不会排队。
  • 嘿,user458。感谢您的反馈意见。我将浏览该页面。我确实考虑过将问题分开。但是,在几个单独的帖子上发布我的代码感觉很乏味。此外,我认为我已将我的问题标记为“代码审查”。对不起,因为我没有!再次感谢:)
  • 我现在意识到代码审查是一个完全独立的论坛(对不起)。
  • 不用担心。松散的经验法则是在这里放行不起作用的代码。确实有效但可以更好地工作的代码进入代码审查。关于 2) value_type && value 的注释是 forwarding reference(有时称为通用参考)。大多数情况下,您会在ownershipstd::move 的传输中找到这些。

标签: c++ class c++11 queue


【解决方案1】:

我将尝试对 Q1、Q2 和 Q3 给出一些快速的答案(但绝不是完整的,您应该研究用于更好地理解的术语)。就像 cmets 建议的那样,其余的更适合代码审查。

Q1 - A) 由于引用是常量,编译器能够将文字绑定到参数。思路是,如果函数不能修改它,那么 object*/primitive 是定义还是字面量都无关紧要。如果签名是push(value_type & value),那么这将不起作用。此函数期望对允许您修改它的对象/基元的非常量引用。这是没有意义的,因为您不能修改文字,因此是不允许的。

B) 是 enqueue(Queue const & value) 将添加深层副本,但该函数不应该获取值的副本。如果是这样,您将复制所有项目 2 次而不是 1 次。函数enqueue(Queue const value)(获取一个副本)将首先根据您为函数提供的参数构造一个新队列value(请参阅复制构造函数)。然后通过value 并将新元素添加到调用队列的前面,其值与value 中的值相同。因此,在构造参数值和将项目添加到调用队列时,每个项目将被复制两次。

Q2 - 如 cmets 中所述,value_type && value 是转发引用或 r-value 引用。或多或少是对未绑定到 l-value 的值的引用。这使您能够有效地执行push(MyObject(1, 2, 3)) 之类的操作(因为MyObject(1, 2, 3) 尚未绑定到“左值”)或传递所有权。 (参见移动构造函数

Q3 - const T & front() const 第一个const 指返回类型(T&),第二个const 指调用对象(队列)。 front 返回对队列中第一个元素的引用。 T & front() 使您能够获取第一个元素并通过引用对其进行修改(是的,在某些情况下修改队列的前端很有用)。但是如果 Queue 是常量,那么获取第一个元素并修改它就没有意义了。因此,您为用户提供了在 const Queue 上使用的替代方法,const T & front() const。您仍然可以获得对队列前面的引用,但该引用是 const 限定的,因此您无法修改它。根据编译器 - const T & front() const 用于 const Queue,T & front() 用于普通队列。

【讨论】:

  • 附录 3:根据调用参数与函数参数的匹配程度来选择重载。 Grisly details。成员函数的简单视图(通常会出现)是 T & Queue::front() 实际上是 T & front(Queue *) 以传入 this 参数。 T & Queue::front() const 表示thisconst,所以T & front(const Queue *)。函数参数现在不同了,可以调用正确的重载了。
  • 我可以再问几个问题吗? (1) 为什么要将 Queue 声明为 const?不是不能修改 const Queue,即不能添加或删除元素,从而使队列无用吗?
  • (2) 在另一个队列中添加元素的副本不是更好的主意吗?如果我要添加引用,那么我应该制作浅拷贝的复制构造函数是否不能正常工作?
  • 我还删除了 3 之后的所有问题,并根据您的建议将这些问题移至 Code Review。
  • @RafaelVergnaud 你仍然可以偷看一个可用的元素,因为const 引用可以延长临时的寿命,你可以传递一个临时的直到你到达你存储的点它永久。其他人可能有更多的见解,所以这可能是一个很好的独立问题。复制构造函数可以很好地处理引用。您可以深或浅复制参考(您可以通过转让所有权让人们大吃一惊,我不建议这样做。如果您想转让所有权,请使用 &&)。
猜你喜欢
  • 2011-05-14
  • 2012-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-16
  • 2011-03-20
  • 1970-01-01
相关资源
最近更新 更多