【问题标题】:Move constructor (rvalue reference) in implicit conversion在隐式转换中移动构造函数(右值引用)
【发布时间】:2010-09-15 13:31:17
【问题描述】:

我正在将一个 C++ 项目从 MSVC 2008 升级到 2010,并且由于新的 CComBSTR 移动构造函数 [CComBSTR( CComBSTR&& )],由于调用不明确,我收到了编译器错误。

本质上,我们有一个 String 类,与 std::wstring 非常相似,它有一个转换为 CComBSTR 的运算符。这类似于以下代码:

class CString {
  public:
    // ...
    operator CComBSTR() {
      CComBSTR temp;
      /* Encoding conversion here */
      return temp;
    }
}

class CObjectConfig {
  public:
    CString GetName() const { return m_name; }

  private:
    CString m_name;
}

现在,在代码中的某些地方,我们执行以下操作:

CObjectConfig config = GetObjectConfig();
CComBSTR objectName( config.GetName() );

在 VS2008 中,这会起作用,因为 CString 对象将被隐式转换为 CComBSTR 右值,并且将调用 CComBSTR 的复制构造函数(采用 const CComBSTR&)来构造 objectName。

然而,在带有 C++0x 的 VS2010 中,编译器给出了一个模棱两可的调用错误,因为 CComBSTR 右值似乎同时适合复制构造函数和移动构造函数。

虽然有点笨拙,但我对这个问题的解决方案是 static_cast 调用 GetName:

CComBSTR objectName( static_cast<const CComBSTR&>( config.GetName() ) );
// or
CComBSTR objectName( static_cast<CComBSTR&&>( config.GetName() ) );

这两行都编译没有错误,但我需要你的建议,看看这是否非法、不好的做法或未定义。谢谢。

【问题讨论】:

    标签: rvalue-reference move-constructor


    【解决方案1】:

    对我来说,这看起来像是一个 VC2010 错误。要么,要么我在我的电脑上错误地模拟了你的情况(我没有 VC2010)。这是我正在做的事情:

    #include <iostream>
    
    class CComBSTR
    {
    public:
        CComBSTR() {std::cout << "CComBSTR()\n";}
        CComBSTR(const CComBSTR&) {std::cout << "CComBSTR(const CComBSTR&)\n";}
        CComBSTR(CComBSTR&&) {std::cout << "CComBSTR(CComBSTR&&)\n";}
    };
    
    class CString {
      public:
        // ...
        operator CComBSTR() {
          CComBSTR temp;
          /* Encoding conversion here */
          return temp;
        }
    };
    
    class CObjectConfig {
      public:
        CString GetName() const { return m_name; }
    
      private:
        CString m_name;
    };
    
    CObjectConfig GetObjectConfig()
    {
        return CObjectConfig();
    }
    
    int main()
    {
        CObjectConfig config = GetObjectConfig();
        CComBSTR objectName( config.GetName() );
    }
    

    对于 g++-4.4 和 clang(使用 -std=c++0x)的我来说,这编译得很好。它要么调用或省略对 CComBSTR(CComBSTR&&) 的调用。我对解决这个可疑错误的建议很简单:

    CComBSTR objectName( CComBSTR(config.GetName()) );
    

    这相当于你的:

    CComBSTR objectName( static_cast<CComBSTR&&>( config.GetName() ) );
    

    但看起来没有那么吓人(而且同样高效)。如果您想继续使用 static_cast,请使用 cast to CComBSTR&&,因为这可能比从 const 左值构造更有效。

    【讨论】:

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