Home > Net >  why would returned value of "make_share<Type>" in function list be rvalue?
why would returned value of "make_share<Type>" in function list be rvalue?

Time:01-06

here is my code:

#include <bits/stdc  .h>

class Quote {
 public:
  Quote() = default;
  Quote(const string& book, double sales_price)    
      : bookNo(book), price(sales_price) {}
  string isbn() const { return bookNo; }

 private:
  string bookNo;
  double price = 0.0;
};

class Basket {
 public:
  void add_item(shared_ptr<Quote>& sale) { items.insert(sale); }    
  double total_receipt(ostream& s) const;

 private:
  static bool compare(const shared_ptr<Quote>& lhs,
                      const shared_ptr<Quote>& rhs) {
    return lhs->isbn() < rhs->isbn();
  }
  multiset<shared_ptr<Quote>, decltype(compare)*> items{compare};
};

int main() {
  Basket item;
  item.add_item(make_shared<Quote>("aaaa", 1));       //here is the problem is   
  return 0;
}

when i complier it.I got wrong message cannot bind non-const lvalue reference of type ‘std::shared_ptr&’ to an rvalue of type ‘std::shared_ptr’ Then i change code to this:

#include <bits/stdc  .h>

class Quote {
 public:
  Quote() = default;
  Quote(const string& book, double sales_price)    
      : bookNo(book), price(sales_price) {}
  string isbn() const { return bookNo; }

 private:
  string bookNo;
  double price = 0.0;
};

class Basket {
 public:
  void add_item(const shared_ptr<Quote>& sale) { items.insert(sale); }      //after debug  i add  "const" at the front of  ''shared_ptr<Quote>& sale'',it works
  double total_receipt(ostream& s) const;

 private:
  static bool compare(const shared_ptr<Quote>& lhs,
                      const shared_ptr<Quote>& rhs) {
    return lhs->isbn() < rhs->isbn();
  }
  multiset<shared_ptr<Quote>, decltype(compare)*> items{compare};
};

int main() {
  Basket item;
  item.add_item(make_shared<Quote>("aaaa", 1));       //here is the problem is   
  return 0;
}

It works.So that means make_shared<Quote>("aaaa",1)returns a rvalue type? But i change function main() to this:

int main() {
  Basket item;
  shared_ptr<Quote> ptr = make_shared<Quote>("aaaa", 1);
  item.add_item(ptr);
  cout << endl;
}

and delete const at the front of shared_ptr<Quote>& salein function list void add_item( const shared_ptr<Quote>& sale) { items.insert(sale); }.It also woks.So that means make_shared<Quote>("aaaa",1) returns a lvalue type.It conflicts to mentioned before. So can i think that when make_shared<Quote>("aaaa",1)in a function list ,it returns rvalue? I also wanna know why would be this.Thanks!

CodePudding user response:

std::make_shared returns a std::shared_ptr<...>, which is not a reference type, therefore the expression std::make_shared<...>(...) is a prvalue (a subcategory of rvalues). This is true for all functions returning objects by-value, rather than by-reference.

Non-const lvalue references cannot bind to rvalues, as the message is telling you, while const lvalue references and rvalue references can.

The line

shared_ptr<Quote> ptr = make_shared<Quote>("aaaa", 1);

works, because there is a constructor of shared_ptr<Quote> which accepts rvalues, namely the move constructor.

In the line

item.add_item(ptr);

the expression ptr is a lvalue. The names of variables used as expressions are always lvalues. And because the type of ptr is not const-qualified, a non-const lvalue reference can bind to it.


returns a rvalue type

rvalue and lvalue are value categories. These are not properties of types, they are properties of expressions. I think you might be confusing them with rvalue references and lvalue references, which are qualities of types.

CodePudding user response:

So that means make_shared("aaaa",1) returns a lvalue type.It conflicts to mentioned before.

No, it doesn't mean that make_shared<Quote>("aaaa",1) returns an lvalue type.

From std::make_shared:

std::make_share returns an expression whose value category is an rvalue.

The reason your last case works is explained below.

When you wrote:

shared_ptr<Quote> ptr = make_shared<Quote>("aaaa", 1); //this is initialization and uses one of shared_ptr's constructor

The above statement means 2 things:

  1. ptr is an object of type shared_ptr<Quote>
  2. The value category of expression ptr is lvalue.

Next, you wrote:

item.add_item(ptr); //this works because the expression ptr is an lvalue

And since we can bind a non-const lvalue reference to an lvalue there is no error in this case even if you remove the const from add_item's parameter.

  •  Tags:  
  • Related