Ahmad S
Ahmad S

Reputation: 98

static_cast to r-value references and std::move change their argument in an initialization

The following simple code shows that static_cast to r-value reference type and std::move may change their input argument (here variable inupt) in an initialization statement depending on the type of the object getting initialized. Can someone explain this behavior?

I am at least glad that static_cast and std::move behave similarly since std::move does use static_cast under the hood

#include <iostream>
#include <string>

int main() {

   {
      std::string input("hello");
      std::string&& result = static_cast<std::string&&>(input);
      std::cout << "cast case 1: input: " << input << " result: " << result << std::endl; // prints: cast case 1: input: hello result: hello
   } 

   {
      std::string input("hello");
      std::string result = static_cast<std::string&&>(input);
      std::cout << "cast case 2: input: " << input << " result: " << result << std::endl; // prints: cast case 2: input:  result: hello
   }

   {
      std::string input("hello");
      static_cast<std::string&&>(input);
      std::cout << "cast case 3: input: " << input << std::endl; // prints: cast case 3: input: hello
   }

   {
      std::string input("hello");
      std::string&& result = std::move(input);
      std::cout << "move case 1: input: " << input << " result: " << result << std::endl; 
      // prints: move case 1: input: hello result: hello
   } 

   {
      std::string input("hello");
      std::string result = std::move(input);
      std::cout << "move case 2: input: " << input << " result: " << result << std::endl; 
      // prints: move case 2: input:  result: hello
   }

   {
      std::string input("hello");
      std::move(input);
      std::cout << "move case 3: input: " << input << std::endl; 
      // prints: move case 3: input: hello
   }

}

Upvotes: 0

Views: 495

Answers (2)

R Sahu
R Sahu

Reputation: 206577

The behavior you are observing is not surprising and makes sense.

When you use

  std::string result = static_cast<std::string&&>(input);

the move constructor is called to initialize result. It makes sense that the move constructor will move the contents of input to result.

Contrast that with

  std::string&& result = static_cast<std::string&&>(input);

Here, result is not a new object. It's just a r-value referene to input. There is nothing here that requires the contents of input to be moved.

Upvotes: 2

eerorika
eerorika

Reputation: 238341

at least static_cast and std::move behave similarly since std::move does use static_cast

Not only similarly, but they do exactly the same thing. std::move is a static cast to an rvalue reference.

Can someone explain this behavior?

  1. result is a reference that refers to input. Binding a reference does not modify the referred object.
  2. An object is initialised. Since it is initialised from an rvalue, the move constructor is used. As per documentation of std::string, the input object is left in an unspecified but valid state, which may but might not be different from what it was before being moved from.
  3. The result of the cast is discarded. This has no side-effects, and input will not be modified.

Upvotes: 0

Related Questions