隐式构造函数自动使用(并且不正确)

时间:2015-06-03 03:05:36

标签: c++ visual-c++

我正在尝试使用以下代码尝试实例化名为InterpreterMacroAssembler的C ++类的一些代码(OpenJDK 8 VM的一种变体,如果你想知道):

// interpreter.hpp
CodeletMark(InterpreterMacroAssembler*& masm,
            const char* description,
            Bytecodes::Code bytecode = Bytecodes::_illegal):
    _clet((InterpreterCodelet*)AbstractInterpreter::code()->request(codelet_size())),
    _cb(_clet->code_begin(), _clet->code_size())
{
    // request all space (add some slack for Codelet data)
    assert (_clet != NULL, "we checked not enough space already");

    // initialize Codelet attributes
    _clet->initialize(description, bytecode);
    // create assembler for code generation
    masm  = new InterpreterMacroAssembler(&_cb);
    _masm = &masm;
}

// macroAssembler_x86.hpp
MacroAssembler(CodeBuffer* code) : Assembler(code) {}

问题是,编译器发出C2664错误,因为它认为我尝试调用隐式创建的复制构造函数(签名为ImplicitMacroAssembler(const ImplicitMacroAssembler &)),而且是抛出类型不匹配错误,因为我没有传递相同类型的对象。我已经验证(通过使用明智的#pragma message)编译器正在看到正确的构造函数,但由于某种原因它没有被使用。是否有任何理由为什么C ++编译器更喜欢隐式生成的复制构造函数而不是显式编写的(但不是explicit,在C ++关键字意义上)用户定义的构造函数?

更改上面的代码,将新的InterpreterMacroAssembler实例存储在本地变量中(我称之为masm2),然后将masm2放入masm与上述相同的变量和_masm变量,不会改变任何内容。

我使用的是Microsoft Visual Studio 2015 Release Preview,cl版本19.00.22816,如果有帮助的话。

1 个答案:

答案 0 :(得分:1)

根据问题的文字说明:

void foo (InterpreterMacroAssember*& masm) {
    //... do something with masm
}

//...
CodeBuffer _cb;
foo(new InterpreterMacroAssembler(&_cb));

由于您正在引用临时指针,因此会失败。

您误解了错误代码。在您引用的文档页面中:

  

'function' : cannot convert parameter number from 'type1' to 'type2'
  如果创建了类的实例并且在使用explicit关键字标记的构造函数上尝试进行隐式转换,则可能会发生此参数转换问题。有关显式转换的详细信息,请参阅转换   如果将临时对象传递给将对象引用作为参数的函数,则该引用必须是const引用。

你可能遇到了我强调的第二段中解释的问题。

要修复此问题,请将参数设为const参考。由于它是一个指针参数,const关键字需要位于引用和指针类型指示符之间。

void foo (InterpreterMacroAssember* const & masm) {  //...

但是,首先考虑参考是有点愚蠢的。除非Java接口需要它,否则将函数更改为仅采用指针参数更为直接。

void foo (InterpreterMacroAssember* masm) {  //...