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_sharereturns 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:
ptris an object of typeshared_ptr<Quote>- The value category of expression
ptris 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.
