我正在尝试使用以下代码尝试实例化名为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,如果有帮助的话。
答案 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) { //...