New and delete are a thing of the past, with the new features in C++14 and beyond (such as smart pointers and move semantics) memory management is easier and safer. Learn how to use the new constructs of C++14 and beyond to create, move, and free objects in a safer and more efficient manner.
2. Who is Alan
Uthoff?
• Founder and CEO of Swordpoint Studio, LLC
• Professional game developer 10+ years in C++
• Runs the C++ 17 Advanced Mentoring and Study
Group - Austin (CppMSG) and Austin Qt and QML
Developers Meetup
8. C++ 98 Factory
//With double pointers
void myClassFactory(myClass ** myDoublePtr)
{
*myDoublePtr = new myClass();
}
//return by pointer
myClass * myClassFactory()
{
return new myClass();
}
//Creates a lot of copies not very performant function
std::string myStringFactory()
{
//Creates two strings here
return "Hello World";
}
9. C++ 14 Factory
// 98 way
//With double pointers
void myClassFactory(myClass **
myDoublePtr)
{
*myDoublePtr = new myClass();
}
//return by pointer
myClass * myClassFactory()
{
return new myClass();
}
//Creates a lot of copies not very
performant function
std::string myStringFactory()
{
//Creates two strings here
return "Hello World";
}
// 14 way
std::unique_ptr<myClass> myClassFactory()
{
return make_unique<myClass>();
}
std::string myStringFactory()
{
//Returned by move
return "Hello World";
}
std::string myStringFactory()
{
std::string temp("Hello World");
//Returned by move or
//Copy Elision for prvalues in C++
//17 optional in C++ 11 and 14
return std::move(temp);
}
10. Move Semantics
• Adds new constructor and assignment operator
• myClass(myClass && other) //move constructor
• myClass & operator=(myClass && other ) //move assignment
operator
• std::move cast lvalue to rvalue
13. Copy Elision
• Constructs the object in place avoiding extra copies
• T x = T(T(T()));// only one call to default constructor of T, to initialize
• T f() { return T{}; }
• T x = f(); // only one call to default constructor of T, to initialize x
• T* p = new T(f()); // only one call to default constructor of T, to
initialize *p
• Guaranteed for prvalues in C++ 17
• Optional in C++ 11 and 14
Examples taken from http://en.cppreference.com/w/cpp/language/copy_elision
14. std::shared_ptr
• #include <memory>
• make_shared
• Copy constructor or copy assignment of the shared_ptr
increments refcount
• Decrements when the shard pointer instance is destroyed
16. std::shared_ptr example
void processData(std::shared_ptr<dataClass> p)
{
// thread-safe, even though the shared use_count is
incremented
std::shared_ptr<dataClass> lp = p;
lp->threadSafeProcessData();
}
auto p = std::make_shared<dataClass>();
std::thread t1(processData, p), t2(processData, p),
t3(processData, p);
p.reset(); // release ownership from main
t1.join(); t2.join(); t3.join();
std::cout << "All threads completed, the last one deleted
Derivedn";
Example taken http://en.cppreference.com/w/cpp/memory/shared_ptr
17. std::weak_ptr
• #include <memory>
• std::weak_ptr
• user_count
• expired
• rest
• lock
• Does not increment the shared_ptr only the control block
18. std::weak_ptr example
auto sharedptr =
std::make_shared<int>(42);
std::weak_ptr<int> weakptr = sharedptr;
if (auto validSharedptr =
weakptr.lock())
{
//good ptr use validSharedptr
}else{
//memory is gone nullptr
}
19. Working with Legacy Code
void legacyFunction(const myClass * ptr )
{//do something …}
void legacyFunctionTakesOwnership(const myClass * ptr )
{//do something …}
myFactoryClass * legacyFactory( )
{return new myFactoryClass();}
void legacyFactoryDestroy(myFactoryClass * )
{delete myFactoryClass;}
int main()
{
auto uniquePtr = make_unique<myClass>();
legacyFunction(uniquePtr.get());
auto uniquePtr2 = make_unique<myClass>();
legacyFunctionTakesOwnership(uniquePtr2.release());
//can add a deleter as the second argument unique_ptr to have legacyFactoryDestroy
//called automaticity
std::unique_ptr<myFactoryClass> myFactoryPtr(legacyFactory());
legacyFactoryDestroy(myFactoryPtr.release());
}
20. std::any
• A type safe object that can hold any type of object
• Is a replacement for void pointers
• #include <any>
• std::any
• operator=
• emplace
• reset
• has_value
• type
• any_cast
• make_any
• bad_any_cast