1

I read a lot of information about rvalue links, I understood everything, but I met this example:

template<class T, class Arg> T* make_raw_ptr(Arg &&arg) { return new T(arg); }; 

If you pass rvalue to the make_raw_ptr function without using the my_forward function, when using new T, there will be a copy constructor, not a move constructor. I understand that arg will be lvalue, despite the fact that it is an rvalue reference, but I have one question. Why make a static_cast arg to an rvalue link when it is already an rvalue link, while using a static_cast<A&&> to arg, the move constructor will be called?

5
  • That's not an "rvalue link" ; it's a forwarding reference because it is in a deduced context. I think you'll find this page highly informative. Commented May 13, 2022 at 4:53
  • I think I figure it out... Rvalue reference is lvalue because it is reference and we can imagine it as "const Arg &arg = rvalue", but without const ofc. In this case, there is copy constuctor will be called, not move. Am I right? @WhozCraig Commented May 13, 2022 at 5:48
  • @malloc this is just a mental model, but in general: if it is has a name, it's an lvalue, unless explicitly cast to rvalue. As for the example you gave, arg is neither lvalue nor rvalue reference, it's a forwarding reference which is deduced at compile time to either r- or l- value one. Commented May 13, 2022 at 6:04
  • @alagner why isn't arg lvalue? Here is said "An rvalue reference behaves just like an lvalue reference except that it can bind to a temporary". It explains why copy constructor will be called in my example. Commented May 13, 2022 at 6:16
  • @malloc it's been answered already: it's a template argument deduced at compile time, so it's a forwarding reference (from caller's perspective). Inside the function make_raw_ptr it generally is an lvalue as (to put it simply) it has a name. See this for more info. Commented May 13, 2022 at 6:28

1 Answer 1

3

arg itself is an expression that represents an object referred to by arg and its value category is lvalue. It doesn't matter what the type of arg actually is. A name of a variable / function parameter itself is always an lvalue expression.

static_cast<A&&>(arg) is an expression that represents the very same object as arg, but its category is rvalue (and xvalue). When you use this expression as the constructor argument, the move constructor will be preferred. The same effect is with std::move(arg).

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.