对下面的代码感到有点困惑。 `
class sample
{
public:
sample() { }
sample( sample& Obj ) { }
};
void fun( sample& Obj ) { }
int main()
{
sample s(sample());
fun( sample() );
return 0;
}
我收到以下错误
由于以下错误导致编译失败。 main.cpp:在函数' int main()': main.cpp:29:19:错误:类型'样本&'的非const引用的无效初始化来自类型'样本'的左值fun(sample());
我理解从样本&中改变乐趣的论点obj to const sample& obj将解决错误。
我的问题是,即使对于复制构造函数,也发送了一个临时对象。但是为什么编译器没有抛出相同的错误。
非常欢迎很好的解释
此致 Prasath S。
答案 0 :(得分:6)
这一行:
sample s(sample());
是一个名为s的函数声明,它返回一个示例对象,并将一个不带参数的函数作为参数,并返回一个示例对象。你根本没有调用复制构造函数。它被称为“最令人烦恼的解析”。虽然有些人反对这个名字。
通过写入控制台或在复制构造函数中放置断点,您可以看到这种情况,它永远不会被调用。您将看到的另一件事是向您的类添加变量成员并尝试访问它将无法正常工作。行之后:
sample s(sample());
尝试使用:
s.sampleMember = 1;
它将无法编译,理由是s是函数声明而不是对象。有两种方法可以避免这种情况,您可以在另一组括号中包围该参数:
sample s((sample()));
或者您可以使用C ++ 11向前样式括号初始化,例如:
sample s(sample{});
答案 1 :(得分:3)
这里有两个问题:
这一行是“最令人烦恼的解析”问题:
sample s(sample());
,就像已经提到过的那样。 您正在声明函数获取函数,没有参数作为参数并将sample作为值返回。使用示例s((sample()))等大括号或使用新的c ++ 11语法示例s(示例{})解决了这个问题。
另一个是非const左值参考不能绑定到右值,你的意图可能是在行中:
fun( sample() );
您必须将有趣的参数声明为:
void fun( const sample& Obj ) { }
或(从c ++ 11开始)
void fun( sample&& Obj ) { }
(假设你不想在乐趣中改变Obj)然后只有 const左值引用或 rvalue references 可以绑定到rvalues。 否则,如果您的目的是在乐趣中改变Obj,则必须保留声明非常量左值引用:
void fun(sample& Obj ) { }
并用一些左值调用它,比如
fun(s)