简体   繁体   中英

No conversion from long unsigned int to long unsigned int&

I receive the error message No known conversion for argument 2 from long unsigned int to long unsigned int& when I try to compile the following code:

void build(int* &array, unsigned long& index) {
  if (index == 0)
    return;
  else {
    heapify(array, index);
    build(array, index-1);
  }
}

Can someone explain why this happens, and what the logic is behind this error?

The second argument of build requires a reference (marked with & ). A reference is kind of like a pointer, so you can only use an actual variable that has a memory address.

This is why you can't use an expression like index-1 .

A non-const reference may only be bound to an lvalue in C++. index-1 returns a temporary, which, if bound to a reference would immediately go out of scope and you would have a dangling reference. A const reference can be bound to a temporary though, and it will prolong the lifetime of the temporary to the lifetime of the const reference. So, if you can change unsigned long& to const unsigned long& it should work.

The second argument of build is a reference to unsigned long . But in the recursive call, you pass it an actual value (ie an "rvalue").

If you rewrite the function as follows, the problem should disappear.

void build(int* &array, unsigned long& index) {
   if (index == 0)
     return;
   else {
    heapify(array,index);
    index -= 1;
    build(array,index);
  }
}

But note that this might not be what you want. The value of index will be changed before the recursive call. You might want to change it back ( index += 1 ) after the call, depending on what the overall purpose of the function is.

See The Design and Evolution of C++ , chapter 3.7, p86, which gives this example:

void incr(int& rr) { rr++; }

void g()
{
    double ss = 1;
    incr(ss)     // note: double passed, int expected
                 // (fixed: error in Release 2.0)
}

In the first version of C++ a temporary of type int was created from the double , with value 1 , then that temporary was passed to incr and ss was not modified. To prevent this sort of unexpected behaviour the language was changed so that a temporary (ie an unnamed variable) cannot bind to a non-const reference, because a non-const reference parameter usually implies the parameter will be modified to pass information back to the caller. If a temporary is silently created the caller loses that information, eg

void* get_ptr(int& error);  // sets error=0 if returned pointer is valid

void g()
{
    unsigned err = 0;        // oops, wrong type
    void* p = get_ptr(err);  // uh-oh, error status stored in temporary
    if (err == 0)            // condition always true
        use_ptr(p);          // uh-oh! pointer may not be valid!
}

If a non-const reference is allowed to bind to a temporary then this program is dangerous, because get_ptr(err) will create a temporary int , like get_ptr(int(err)) , and set the error status in the temporary, so err will still be zero even if there's a problem.

If the function author wants to be able to accept temporaries, because the argument won't be used to pass information back to the caller, then the function can take parameters by value:

void blah(int rr);

or by const-reference:

void blah(const int& rr);

what line is your error message on? It seems like you are passing in a long unsigned int for index, when it needs a long unsigned int by reference (in other words the address of the long unsigned int )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM