admin管理员组

文章数量:1395730

I'm trying to figure out how C++ actually breaks down the argument-passing when the formal argument is a reference and the actual argument is of a type that requires type-conversion.

  • Here's an example. Are the calls to f(10) and g(5) supposed to compile/run or they supposed to throw an error?

f(10) passes an int but the formal-argument is a reference to const. So the compiler has to bind the reference to 10. How does it do that? What assignment statement does it create to bind it? would it create a temporary object (say tmp) and insert a statement like A tmp(10); f(tmp); instead of call to f(10)?

class A {
public:
    A(int);
    ~A() = default;
};

void f(const A&);
void g(A&);

f(10);
g(5);
  • Can someone elaborate on what type-conversion and argument-passing rules apply here?

  • When running g(5) call I get the error:

    error: cannot bind non-const lvalue reference of type ‘A&’ to an rvalue of type ‘A’

    Can someone explain the reasoning behind this?

I'm trying to figure out how C++ actually breaks down the argument-passing when the formal argument is a reference and the actual argument is of a type that requires type-conversion.

  • Here's an example. Are the calls to f(10) and g(5) supposed to compile/run or they supposed to throw an error?

f(10) passes an int but the formal-argument is a reference to const. So the compiler has to bind the reference to 10. How does it do that? What assignment statement does it create to bind it? would it create a temporary object (say tmp) and insert a statement like A tmp(10); f(tmp); instead of call to f(10)?

class A {
public:
    A(int);
    ~A() = default;
};

void f(const A&);
void g(A&);

f(10);
g(5);
  • Can someone elaborate on what type-conversion and argument-passing rules apply here?

  • When running g(5) call I get the error:

    error: cannot bind non-const lvalue reference of type ‘A&’ to an rvalue of type ‘A’

    Can someone explain the reasoning behind this?

Share Improve this question edited Mar 27 at 1:14 Remy Lebeau 601k36 gold badges507 silver badges851 bronze badges asked Mar 27 at 0:39 Joe BlackJoe Black 67310 silver badges24 bronze badges 13
  • 1 The compiler is allowed to make a single implicit conversion to make arguments match, so since a A can be constructed from a int it can make the call to f(10) by converting the integer to an instance of A and then pass that temporary A by const reference to the function. Calling g(5) doesn't work since you can't pass a temporary A by non-const reference. – Jesper Juhl Commented Mar 27 at 0:43
  • 2 @JoeBlack How the compiler materializes the temporary A and pass it to the function is an implementation detail of the compiler. – Jesper Juhl Commented Mar 27 at 0:49
  • 1 It's very similar to converting the call f(10) to f(A{10}). It's not quite the same, since the latter could do an implicit conversion from A to something else, but it's close enough. – Miles Budnek Commented Mar 27 at 0:56
  • 1 @JoeBlack It simply binds the reference to the temporary object. That has no other observable side-effects. Statements are C++ source code level constructs. They're instructions to the compiler that describe the behavior of the program you want it to write. The compiler doesn't implement behavior via C++ statements (aside from a very few places where the standard describes behavior of one source construct in terms of another; but even then it just mandates that they have the same behavior). – Miles Budnek Commented Mar 27 at 1:32
  • 1 Just to be clear, do you understand how reference binding works in a functin parameter in the simpler case (calling f(const A&) and pass a A(5) to it)? Why do you keep talking about the non-existent and unrelated "assignment" or "statement"? The "reference initialization" page on cppreference may help. Also for C++17 and later, read about temporary materialization. – Weijun Zhou Commented Mar 27 at 3:10
 |  Show 8 more comments

1 Answer 1

Reset to default 2

f(10) passes an int but the formal-argument is a reference to const. So the compiler has to bind the reference to 10. How does it do that? What assignment statement does it create to bind it?

It can't bind to 10 directly. It can bind only to a valid A object.

would it create a temporary object (say tmp) and insert a statement like A tmp(10); f(tmp); instead of call to f(10)?

Essentially, yes. A const reference can bind to a temporary, so that is exactly what the compiler does - it implicitly creates an unnamed temporary A object, constructed using 10 as input to its constructor, then passes a reference to that object into f(), and then destroys that object after the full statement that created it is finished (ie in your example, when the ; is reached).

When running g(5) call I get the error error: cannot bind non-const lvalue reference of type ‘A&’ to an rvalue of type ‘A’. Can someone explain the reasoning behind this?

It is because a non-const reference is not allowed to bind to a temporary, so you will have to create a non-temporary A object yourself and then pass it to g() explicitly.

本文标签: