【问题标题】:Why is a non-const rvalue move constructor called in this case?为什么在这种情况下调用非常量右值移动构造函数?
【发布时间】:2018-12-06 14:45:36
【问题描述】:

我看过相关的问题,他们主要讨论是否应该将 const 右值引用作为参数。但我仍然无法解释为什么在以下代码中调用了 非 const 移动构造函数

    #include <iostream>
    using namespace std;

    class A 
    {
    public:
      A (int const &&i) { cout << "const rvalue constructor"; }
      A (int &&i) { cout << "non const rvalue constructor"; }
   };


   int const foo (void)
   {
     const int i = 3;
     return i;
   }

  int main (void)
  {
     A a(foo());
  }

【问题讨论】:

  • 与您的问题无关,但是从函数返回 const 值确实毫无意义。无论如何都不会阻止调用者将值存储在非常量变量中。
  • @Someprogrammerdude,那你怎么能得到 const rvalues 呢?
  • 只是为了好玩,try your sample with a non-scalar type。 ttbomk 标量的 const prvalue 是虚构的。
  • @sanjivgupta 常量“值”是什么类型的?你的意思是?用例是什么?
  • @sanjivgupta 没有 const int 右值这样的东西。

标签: c++ language-lawyer move-semantics


【解决方案1】:

这里是您的代码稍作修改的版本:

#include <iostream>

#if 0
using T = int;
#else
struct T {T(int){}};
#endif

    using namespace std;
    class A {
      public:
      A (T const &&i) { cout << "const rvalue constructor"; }
      A (T &&i) { cout << "non const rvalue constructor"; }
   };


   T const
   foo (void)
   {
     const T i = 3;
     return i;
   }

  int main()
  {
    A a(foo());
  }

T == int 时,您会得到非常量重载。当T 是类类型时,您将获得 const 重载。此行为不属于第 8.2.2 节 [expr.type]/p2:

如果纯右值最初的类型为“cvT”,其中T 是无 cv 限定的非类、非数组类型,则表达式的类型调整为T 在任何进一步分析之前。

翻译:该语言没有const 限定的标量纯右值。它们根本不存在。

【讨论】:

  • 啊!!我认为 C++ 的设计目标之一是让用户定义类型的行为与内置类型一样。
  • 设计目标经常相互冲突。 C++ 的另一个设计目标是与 C 兼容。
  • @sanjivgupta 傻不是设计目标。只能复制标量。从int 转移是没有意义的!
  • 哦,多么有趣的花絮!
  • @sanjivgupta 复制标量很便宜;比窃取它的价值便宜。因此,从标量移动是正常副本并且不会更改源是合理的。顺便说一句,内置运算符不是重载运算符。 1 + 1. 不会通过重载决议。标量的隐式转换不同于用户定义的转换。指针转换不同于智能指针转换。协变返回类型适用于指针而不是类。 static_cast, dynamic_cast... 不能在类上重载。等等。
猜你喜欢
  • 1970-01-01
  • 2016-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多