Move Construction, part III


Last time, we discussed rvalue references. Rvalue references uniquely identify objects that can be safely moved from. In the move constructor below, rhs is an rvalue reference. It refers to an object, such as a temporary object, that will only exist for another moment before it disappears forever.

Texture( Texture&& rhs ) : // move ctor
   mpBits( std::move( rhs.mpBits ) ),
   mSize ( std::move( rhs.mSize  ) )
{
   rhs.mpBits = nullptr;
}

Now it’s time to discuss std::move() and why std::move() is important.

Recall that rhs is an rvalue reference. However, there’s a problem. It has a name. You can take the address of rhs. Hence, the variable rhs, in the context of the Texture() move constructor, is an lvalue! Let that sink in for a moment.

Despite the fact that the only way the Texture() move constructor could be invoked is if rhs was an rvalue at the point of the call, the compiler must treat rhs as an lvalue in the context of the actual move constructor, because it has a name. In order to inform the compiler to treat rhs as an rvalue, we must use std::move().

std::move() does one thing: tell the compiler to treat the incoming value as an rvalue reference. That’s it. std::move() has zero performance overhead. Think of it as the equivalent of a static cast, with the type deducted automatically:

mpBits( std::move( rhs.mpBits ) );         // equivalent to:
mpBits( static_cast<t&&>( rhs.mpBits ) );  // where T is deducted from mpBits type

std::move() is provided by all C++11 implementations. It’s an inline function, so you can inspect the implementation for yourself should you care to witness reference collapsing and parameter deduction in action.

Takeaways:

  • Use std::move() whenever you need to treat a named variable as an rvalue reference, such as within a move constructor or move assignment operator.
  • std::move() is the equivalent of a cast. It has no performance penalty.
  • std::move() is self-documenting. It indicates to your reader that you intend to move from the object in question.

Now we know about move constructors, rvalue references and std::move(). Next time we’ll put it altogether, compare move constructor to copy constructors, and extract some best practices.

Posted in C++ | Leave a comment

Move Construction, part II


Last time, I provided an introduction to move construction, a new method of constructing objects in C++11. The move constructor looked like this:

Texture( Texture&& rhs ) : // move ctor
   mpBits( std::move( rhs.mpBits ) ),
   mSize ( std::move( rhs.mSize  ) )
{
   rhs.mpBits = nullptr;
}

The && notation is a little strange: two ampersands in a row. This is not a logical AND. This notation is called an rvalue reference. Rvalue references are a new feature of C++11, and they are at the core of enabling move semantics.

Before we can talk about rvalue references, we first need to talk about rvalues. In C++11, every expression is either an lvalue or an rvalue. I like to think of lvalues as Located in Memory, hence: L-values. Rvalues are not located in memory. They don’t have names, and you can’t take their address. Rvalues are ephemeral. They exist for a brief period of time, typically as temporary objects. Here are some examples:

int x;

x is an lvalue. It has a name. It lives in memory. You can take its address.

int x = 1+2;

1+2 is an rvalue. It doesn’t have a name. It doesn’t live in memory. You can’t take its address.

foo( x );

x is an lvalue. It lives in memory and you can take its address.

foo( bar() );

bar() is a default constructor that returns a bar object. That object is an rvalue. It does not have a name and does not reside in memory. You cannot take its address. In fact, bar() is a classic example of a moveable object. It is a temporary object that does not live beyond the lifetime of foo(). The result of bar() could be “moved” into foo() rather than being copied, if there was some way for the compiler to know that bar() was a moveable object.

Rvalue references to the rescue. Before C++11, a T& represented both lvalue and rvalue references. We simply called a T& a reference. In C++11, there are now two types of references. In C++11, T& is an lvalue reference, and T&& is an rvalue reference.

What does this mean? With C++11, we now have a way of uniquely identifying objects which can be safely moved from. Rvalue references uniquely identify those objects, because rvalue references bind to rvalue expressions and lvalue references bind to lvalue expressions.

Texture( Texture&& rhs ) : // move ctor
   mpBits( std::move( rhs.mpBits ) ),
   mSize ( std::move( rhs.mSize  ) )
{
   rhs.mpBits = nullptr;
}

In the move constructor, we are guaranteed that rhs represents an object that can be safely moved from. Very sweet. The next challenge is understanding exactly what it means to move from an object rather than copy from an object. We’ll cover that next time.

Posted in C++ | 1 Comment

Move Construction, part I


At GDC this year, my presentation covered move construction, a new fast method of constructing objects in C++11. Here’s how it works. Up until C++11, whenever you created a new object from an existing object, you copied the object by using a copy constructor. The copy constructor looks something like this:

Texture( const Texture& rhs ) {
   mSize = rhs.mSize;
   mpBits = new unsigned long [mSize];
   memcpy( mpBits, rhs.mpBits, mSize );
}

The problem that move constructors solve is situations like this:

Texture x( Texture(...) ); // copy from a temporary

In the scenario above, we create a temporary texture object, then we create another texture object x, copy the temporary to x, then tear down the temporary object. That’s a lot of work when it’s very clear to us as programmers that it would be more efficient to simply swap out the guts of the temporary object directly into x. That’s exactly what move constructors allow. Here’s a move constructor in C++11:

Texture( Texture&& rhs ) : // move ctor
   mpBits( std::move( rhs.mpBits ) ),
   mSize ( std::move( rhs.mSize  ) )
{
   rhs.mpBits = nullptr;
}

The move constructor allows us to do exactly what we want: eviscerate the guts from rhs. We leave rhs in a known good state. It is still a C++ object, after all — but one that will immediately be destroyed because it’s a temporary.

As a result, we can gain massive speed improvements. In this scenario, we avoid an extra allocation, a memcpy, and a deallocation. We also avoid having to hold two textures in memory at the same time.

You might have noticed something a little strange, however. The notation for a move constructor uses an unfamiliar && notation, and it passes rhs by non-const. We’ll cover this new C++11 notation next time.

Posted in C++ | 1 Comment

Opportunity Knocking: Windows 8


This is an exciting time to be a game developer. There are simply so many opportunities for studios of all shapes and sizes to get their entertainment in front of big audiences. One of the biggest opportunities around is Windows 8. At GDC we talked about how Windows 8 will be a game changer — pun intended! While I was at GDC, I was interviewed by the Bytes by MSDN team. You can see the interview here to learn more about opportunities across all Microsoft devices.

Posted in Game Programming, Microsoft | Leave a comment

Faster C++: Move Constructors and Perfect Forwarding


Just a few hours ago I delivered my Faster C++ talk at the 2012 Game Developers Conference. This was my thirteenth GDC presentation! The large room was packed, which is awesome, so the topic seemed relevant to the game development community. The great thing is that all major compilers support rvalue references, so it’s very actionable material. In fact, just by upgrading to C++11 you get a free performance boost. If you attended the talk, thanks for coming. You can find a link to the slides here: http://www.tantalon.com/pete.htm. Enjoy move-enabling your game code!

Posted in C++, Game Programming | 4 Comments

Game Developers Conference 2012


GDC is coming up fast: March 5-9 in San Francisco. I’ll be speaking on the latest C++ performance technology — move constructors, perfect forwarding and rvalue references. My session title is Faster C++, 11:30a on Friday, March 9. Microsoft is hosting our annual game developer day, this year entitled “Entertainment Reimagined,” on Tuesday, March 6th. I’ll kick off that event as the master of ceremonies. We’ve packed a ton of great content covering new technologies for Windows 8 and Xbox LIVE across multiple platforms. Be sure to also stop by the Microsoft lobby bar in the North Hall: a great place to meet up with friends, check out the latest games, sign up for Dream.Build.Play 2012, and enjoy some refreshment after a long day of talks and walking the expo floor. See you at GDC 2012!

Posted in C++, Game Programming, Microsoft | Leave a comment

C++11: Getting Up To Speed on the New Standard


C++11 is officially the new C++ International Standard. All those new features that people have been talking about for the last few years, such as lambdas and r-value references, are now Standardized. However, the industry still has a lot of catching up to do. You can find information about what C++11 features are supported by various compilers at these sites:

http://blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx

https://wiki.apache.org/stdcxx/C%2B%2B0xCompilerSupport

http://gcc.gnu.org/projects/cxx0x.html

Finding good reference material for C++11 is still challenging. The Standard is so new, there are no books available at the moment. The best material I’ve found is Scott Meyer’s information. Scott has been investigating C++11 features for some time, and he’s compiled all that’s he’s learned into a great document. You can find more here: http://scottmeyers.blogspot.com/2011/11/c11-training-materials-updated.html

Posted in C++, Microsoft | 2 Comments

My Dad, Steve Jobs, Wizardry and Me


In the fall of 1982, I took a train trip with my dad. I was 14. We traveled to San Francisco to a computer show at the Moscone Center. We stayed at a tiny hotel just off the Tenderloin district. Dad taught me how to put my wallet in my front pocket to keep it safe in the big city. I took my first taxi ride. We went to a restaurant called MacArthur Park. But what I remember most is the huge underground hall packed with booths full of personal computers from companies like Apple and Commodore, external floppy drives (140K!), keyboards, green and amber monochrome monitors, software, and games. My job was to pick out games for our new Apple II computer. The two games I can remember choosing were Choplifter and Wizardry. That copy of Wizardry sits in my office today, still in the original box. At the time I never pictured myself working in the gaming industry, because there was no such industry. Games were created by one or two people.

I used that Apple computer for a few years in high school, but my family quickly switched to MS-DOS PCs, and I didn’t touch an Apple product for more than a decade. Fast forward to 1994. I was working in the game industry. My first task: take an existing Windows title and port it to Macintosh. For the next four years, I used Macs and Windows PCs interchangeably. I didn’t quite realize the effect that Steve Jobs had on my life until recently. If it wasn’t for Apple, I might never have played Wizardry. If it wasn’t for Apple, I might never have had this amazing gaming industry gig. Thanks, Steve. And thanks, Dad, for that SF train trip.

Posted in Computers and Internet, Game Programming | Leave a comment

Windows 8 and C++


Last week Microsoft hosted the //Build/ conference in Anaheim, where we announced the future of Windows software development. There were a lot of exciting announcements, but at the top of my list was Windows 8 embracing C++ as a first class citizen. Not only is C++ one of the many ways to program Windows applications, but it’s core to the Windows runtime (WinRT). WinRT establishes a new application model that is a significant departure from the C-oriented nature of the Win32 model. WinRT adopts key elements of C++. It’s high performance. It’s object-oriented. It’s exception-based.

This has exciting implications for C++ developers. As a developer, you get to reuse all your existing C/C++ libraries. When you need to interface with the Windows runtime, there are a handful of enabling language extensions. The fact that the extensions are built into the language itself means the compiler can do the Right Thing to maximize performance. The other implication is that it’s easy for the thousands of existing C/C++ libraries to be ported to WinRT. It’s a virtuous cycle. You can write in C++, and you can leverage the libraries that other people are writing for WinRT.

For some deeper insight into C++ and Windows 8, be sure to check out Herb Sutter’s talk from //Build/: http://channel9.msdn.com/Events/BUILD/BUILD2011/TOOL-532T

Posted in C++, Microsoft | Leave a comment

C++ Rebirth


I’ve been a C++ guy for a long time. I’ve weathered the Java storm, and .NET, and managed code, and dozens of newer programming languages. I keep coming back to C++, and it appears I’m not alone. For instance, Herb Sutter presented a C++ Renaissance talk at the C++ and Beyond conference this week. And now Microsoft has launched a new show on Channel 9 for native developers called C9::GoingNative. Why all this renewed attention on C++? Simple. The language is powerful but flexible. You can write to the metal or go very high level. The changes in C++0x such as auto and lambdas make it even easier to read and write code. For game developers I work with, whether they’re creating entertainment for consoles, mobile devices or desktops, C++ continues to be the language of choice.

Posted in C++, Game Programming | 2 Comments