复制构造函数在这段代码中出错 - 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输入参数的构造函数可以绑定右值和左值。