在隐式转换中移动构造函数(rvalue引用)

时间:2010-09-15 13:31:17

标签: rvalue-reference move-constructor

我正在将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 rvalue,并且将调用CComBSTR的复制构造函数(采用const CComBSTR&)来构造objectName。

在带有C ++ 0x的VS2010中,编译器给出了一个模糊的调用错误,因为CComBSTR rvalue似乎适合复制构造函数和移动构造函数。

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

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

两行都编译没有错误,但我需要你的建议,这是非法的,坏的做法还是未定义的。谢谢。

1 个答案:

答案 0 :(得分: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&amp;&amp;)的呼叫。我建议解决这个疑似错误的原因很简单:

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

这相当于你的:

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

但不是那么可怕(并且同样有效)。如果你想继续使用static_cast,那么请使用强制转换为CComBSTR&amp;&amp;因为这可能比const lvalue的构造更有效。