复制构造函数在这段代码中出错 - C++08
Error in this piece of code with the copy constructor - C++08
假设我有以下(非常粗糙的)代码
class foo
{
public:
int a;
foo() //Regular constructor
{
......
std::cout << "Regular \n";
}
foo(foo& f) //Copy constructor with with non-const parameter
{
....
std::cout << "Copy Constructor \n" ;
}
foo& operator= (const foo& f)
{
std::cout << "Copy Assignment Operator \n" ;
return *this;
}
};
foo makeFoo()
{
return foo();
}
int main()
{
foo a = makeFoo();
}
现在,当我尝试使用 -fno-elide-constructors
模拟此代码(用于实验和教育目的)时,出现以下错误
main.cpp: In function 'foo makeFoo()':
main.cpp:32:15: error: no matching function for call to 'foo::foo(foo)'
return foo();
^
main.cpp:32:15: note: candidates are:
main.cpp:12:5: note: foo::foo(foo&)
foo( foo& f)
^
main.cpp:12:5: note: no known conversion for argument 1 from 'foo' to 'foo&'
main.cpp:10:5: note: foo::foo()
foo() { std::cout << "Regular \n";}
^
main.cpp:10:5: note: candidate expects 0 arguments, 1 provided
main.cpp: In function 'int main()':
main.cpp:40:20: error: no matching function for call to 'foo::foo(foo)'
foo a = makeFoo(); //Move constrcutor - Move Constructor or with copy elision only regular constrcutor
^
main.cpp:40:20: note: candidates are:
main.cpp:12:5: note: foo::foo(foo&)
foo( foo& f)
^
main.cpp:12:5: note: no known conversion for argument 1 from 'foo' to 'foo&'
main.cpp:10:5: note: foo::foo()
foo() { std::cout << "Regular \n";}
^
main.cpp:10:5: note: candidate expects 0 arguments, 1 provided
main.cpp: In function 'foo makeFoo()':
main.cpp:33:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
现在通过将复制构造函数的参数设为常量类型来解决这些错误。我想知道我对为什么将复制构造函数的参数设为 const 类型的理解是否解决了这个问题。如果我的理解或推理不正确,请告诉我。现在在方法 makeFoo
执行语句 return foo();
之后, foo 的常规构造函数被调用。然后调用 foo 的复制构造函数。现在在我的代码中我有这样的东西:
foo a = makeFoo();
在这种情况下,foo a
的复制构造函数被调用。因为 makeFoo() 的 return 类型是一个右值,它始终是一个常量,而 foo 的复制构造函数是一个非常量,因此当我们试图将常量引用类型传递给一个非-常量引用类型。
正如您所提到的,在您的表达式中 foo a = makeFoo();
makeFoo() 是一个右值。
具有非常量输入参数的构造函数(您的情况)只能绑定左值。 makeFoo()
returns 其实是编译器创建的一个临时对象,编译器不希望你去修改这个随时可以删除的临时对象。因此,当您尝试将右值传递给具有非常量输入参数的构造函数时,编译器将抛出错误。
带const输入参数的构造函数可以绑定右值和左值。
假设我有以下(非常粗糙的)代码
class foo
{
public:
int a;
foo() //Regular constructor
{
......
std::cout << "Regular \n";
}
foo(foo& f) //Copy constructor with with non-const parameter
{
....
std::cout << "Copy Constructor \n" ;
}
foo& operator= (const foo& f)
{
std::cout << "Copy Assignment Operator \n" ;
return *this;
}
};
foo makeFoo()
{
return foo();
}
int main()
{
foo a = makeFoo();
}
现在,当我尝试使用 -fno-elide-constructors
模拟此代码(用于实验和教育目的)时,出现以下错误
main.cpp: In function 'foo makeFoo()':
main.cpp:32:15: error: no matching function for call to 'foo::foo(foo)'
return foo();
^
main.cpp:32:15: note: candidates are:
main.cpp:12:5: note: foo::foo(foo&)
foo( foo& f)
^
main.cpp:12:5: note: no known conversion for argument 1 from 'foo' to 'foo&'
main.cpp:10:5: note: foo::foo()
foo() { std::cout << "Regular \n";}
^
main.cpp:10:5: note: candidate expects 0 arguments, 1 provided
main.cpp: In function 'int main()':
main.cpp:40:20: error: no matching function for call to 'foo::foo(foo)'
foo a = makeFoo(); //Move constrcutor - Move Constructor or with copy elision only regular constrcutor
^
main.cpp:40:20: note: candidates are:
main.cpp:12:5: note: foo::foo(foo&)
foo( foo& f)
^
main.cpp:12:5: note: no known conversion for argument 1 from 'foo' to 'foo&'
main.cpp:10:5: note: foo::foo()
foo() { std::cout << "Regular \n";}
^
main.cpp:10:5: note: candidate expects 0 arguments, 1 provided
main.cpp: In function 'foo makeFoo()':
main.cpp:33:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
现在通过将复制构造函数的参数设为常量类型来解决这些错误。我想知道我对为什么将复制构造函数的参数设为 const 类型的理解是否解决了这个问题。如果我的理解或推理不正确,请告诉我。现在在方法 makeFoo
执行语句 return foo();
之后, foo 的常规构造函数被调用。然后调用 foo 的复制构造函数。现在在我的代码中我有这样的东西:
foo a = makeFoo();
在这种情况下,foo a
的复制构造函数被调用。因为 makeFoo() 的 return 类型是一个右值,它始终是一个常量,而 foo 的复制构造函数是一个非常量,因此当我们试图将常量引用类型传递给一个非-常量引用类型。
正如您所提到的,在您的表达式中 foo a = makeFoo();
makeFoo() 是一个右值。
具有非常量输入参数的构造函数(您的情况)只能绑定左值。 makeFoo()
returns 其实是编译器创建的一个临时对象,编译器不希望你去修改这个随时可以删除的临时对象。因此,当您尝试将右值传递给具有非常量输入参数的构造函数时,编译器将抛出错误。
带const输入参数的构造函数可以绑定右值和左值。