C++ without new and delete
by Mikhail Matrosov
mikhail.matrosov@gmail.com
mmatrosov@aligntech.com
Instead of contents
• What?
– Avoid new and delete in modern C++
• Why?
– new and delete increase complexity
• How?
– std::make_shared, std::make_unique
– Containers (STL, boost, libcds, etc.; or your own)
– Wrappers for third-party smart pointers
– Wrappers for libraries with specific memory management
C++ Russia, Moscow, 2015 2
Modern С++
• Modern С++ includes
– С++14 features
– Modern best practices
• C++14 is officially released
– ISO/IEC 14882:2014 / December 15, 2014
– Fully or partially supported by all major compilers
C++ Russia, Moscow, 2015 3
What & how?
Managing memory and objects from C to modern C++
C++ Russia, Moscow, 2015 4
Objects in С
typedef struct ObjectTag
{
// Object members
} Object;
int InitObject(Object* io_pObject);
int UseObject(Object* io_pObject);
int ClearObject(Object* io_pObject);
void ObjectsInC()
{
Object* pObject;
pObject = malloc(sizeof(Object)); // Allocate memory
InitObject(pObject); // Establish invariants and acquire resources
UseObject(pObject); // Do the work
ClearObject(pObject); // Release resources
free(pObject); // Release memory
// By the way: error handling :-/
}
C++ Russia, Moscow, 2015 5
Objects in С++
• Encapsulation:
– Constructors
– Destructors
– Methods
class Object
{
// Object members
public:
Object(); // Establish invariants and acquire resources
~Object(); // Release resources
void Use(); // Do the work
};
• Error handling:
– Exceptions
C++ Russia, Moscow, 2015 6
new
• Allocate memory
• Initialize object
in constructor
delete
• Deinitialize object
in destructor
• Free memory
C++ Russia, Moscow, 2015 7
new creates a single object on the heap
– Usually to share the object
new[] creates a number of objects on the heap
– Usually when number is known at runtime or is big enough
Objects in С++
// 1. Naive C++ style
Object* p = new Object();
p->Use();
delete p;
// 2. More secure C++98 with RAII
std::auto_ptr<Object> ap(new Object());
ap->Use();
// 3. More secure C++11 with RAII
std::unique_ptr<Object> up(new Object());
up->Use();
// 4. New bullet-proof modern C++
auto up2 = std::make_unique<Object>();
up2->Use();
C++ Russia, Moscow, 2015 8
Shared objects in С++
void UseObject(Object*); // Shall only observe the object
void AcceptObject(Object*); // Shall delete the object
void ShareObject(std::shared_ptr<Object>); // May do both!
// Naive C++
Object* p = new Object();
p->Use();
UseObject(p); // Preserve ownership
p->Use();
AcceptObject(p); // Transfer ownership
// C++98 & RAII
/* No way standard to say this! */
// Modern C++
auto sp = std::make_shared<Object>();
sp->Use();
ShareObject(sp); // Share
sp->Use();
ShareObject(std::move(sp)); // Share and discard ownership
C++ Russia, Moscow, 2015 9
Reference counting objects in С++
// Naive C++ (not used)
RefCounted* p = new RefCounted();
p->AddRef();
p->Use();
p->Release();
// C++98 & RAII
RefPtr<RefCounted> rp = new RefCounted();
rp->Use();
// Modern C++
auto rp2 = MakeRefPtr<RefCounted>();
rp2->Use();
C++ Russia, Moscow, 2015 10
Dynamic arrays in С++
void UseArray(int* ptr, int count);
int n = 100;
// Naive C++
int* p = new int[n];
UseArray(p, n);
delete[] p;
// C++98 & RAII
std::vector<int> v(n);
UseArray(&v[0], v.size());
// Modern C++
std::vector<int> v2(n);
UseArray(v2.data(), v.size());
C++ Russia, Moscow, 2015 11
Why?
Advantages of make functions
C++ Russia, Moscow, 2015 12
Better == simple
• A bit of authority:
– Software's Primary Technical Imperative: Managing Complexity
[McConnel2004]
– Make Simple Tasks Simple! [Stroustrup2014]
– ≈99.9998% developers are not experts [Sutter2014]
– KISS principle (Keep It Simple, Stupid)
• What is simple?
– Keep simple things simple
– Don’t make complex things unnecessarily complex
– Write for clarity and correctness first, optimize later
• How to keep it simple?
– DRY principle (Don’t Repeat Yourself)
– “By default” principle [Sutter2014]
C++ Russia, Moscow, 2015 13
“By default” principle
• The main point:
– Common task ⇔ common solution
• Advantages:
– Mutual understanding with other developers
• Programs are parallelized in development-time too!
– Easy for beginners
– Less to think – productive laziness 
– Same as for coding conventions
• See also “A tour of C++” [Stroustrup2013]
C++ Russia, Moscow, 2015 14
std::make_unique<T>() vs.
std::unique_ptr(new T)
int GenerateId();
std::pair<std::unique_ptr<Object>, int> MakeObjectWithIdWrong()
{
return std::make_pair(
std::unique_ptr<Object>(new Object()),
GenerateId());
}
std::pair<std::unique_ptr<Object>, int> MakeObjectWithIdRight()
{
return std::make_pair(
std::make_unique<Object>(), // Safe
GenerateId());
}
DRY!
C++ Russia, Moscow, 2015 15
// May throw!
Exactly the same for std::shared_ptr
and std::make_shared!
// May leak!
std::make_shared<T>() vs.
std::shared_ptr(new T)
std::shared_ptr<Object> sp(new Object());
counter
Object
sp
Two memory
allocations
C++ Russia, Moscow, 2015 16
std::make_shared<T>() vs.
std::shared_ptr(new T)
auto sp = std::make_shared<Object>();
counter Object
One memory allocation.
We Know Where You Live
optimization [Lavavej2012].
sp
C++ Russia, Moscow, 2015 17
Advantages of make functions
• Both:
– Exception safe
– No type name duplication
– Symmetry
• std::make_shared:
– Single memory allocation
C++ Russia, Moscow, 2015 18
std::make_shared and std::weak_ptr
counter Object
sp
C++ Russia, Moscow, 2015 19
wp
auto sp = std::make_shared<Object>();
std::weak_ptr<Object> wp = sp;
sp.reset();
When not to use make functions
• Both:
– Cannot specify custom deleters
– Cannot pass braced initializer
• std::unique_ptr:
– Cannot specify custom allocator (for std::shared_ptr there is
std::allocate_shared function) [see N3588, section IV.4]
• std::shared_ptr:
– Potential memory waste for long-living weak pointers
– Works poorly with class-specific operators new&delete
– Potential false sharing of the object and the reference counting
block [see question on StackOverflow]
• See also “Effective modern C++”, Item 21 [Meyers2014]
C++ Russia, Moscow, 2015 20
Summary
• By default, raw delete is not used in C++ since RAII
and standard containers
• By default, raw new is not used in modern C++ within
the standard library
• If either is used, situation is not default and requires
special handling (and, probably, special attention)
C++ Russia, Moscow, 2015 21
Beyond standard library
Different memory management techniques in C++
C++ Russia, Moscow, 2015 22
Memory management techniques
• No memory management
– Explicit new and delete
– Not used in good code
• Non-intrusive smart pointers
– Applicable for all objects
– Standard library
• Intrusive smart pointers
– Reference counting objects
– Third-party libraries
• Other
– Parent to child relationships, coupling with system resources
– Qt, MFC
C++ Russia, Moscow, 2015 23
Reference counting objects
• OpenSceneGraph
– Open source 3D framework written in C++ and OpenGL
– osg::Referenced – base reference counting class
• ref() increments counter
• unref() decrements counter and deletes the object when counter
drops to zero
– osg::ref_ptr<T> – smart pointer
• Calls ref() on construction
• Calls unref() on destruction
C++ Russia, Moscow, 2015 24
OSG: C++ & RAII
• Official code sample from [Wang2010, p. 78]
• Perfect fit for upgrade
– Can be done automatically
osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
// Init vertices
osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array;
// Init normals
osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
geom->setVertexArray(vertices.get());
geom->setNormalArray(normals.get());
// Further init geometry and use it
C++ Russia, Moscow, 2015 25
OSG: Modern C++
namespace osg
{
template<typename T, typename... Args>
osg::ref_ptr<T> make_ref(Args&&... args)
{
return new T(std::forward<Args>(args)...);
}
}
auto vertices = osg::make_ref<osg::Vec3Array>();
// Init vertices
auto normals = osg::make_ref<osg::Vec3Array>();
// Init normals
auto geom = osg::make_ref<osg::Geometry>();
geom->setVertexArray(vertices.get());
geom->setNormalArray(normals.get());
// Further init geometry and use it
C++ Russia, Moscow, 2015 26
Other memory management
• MFC (Microsoft Foundation Class)
– C++ wrapper classes for Windows API
– CWnd – base class for all windows objects
• Represents both a C++ object and an HWND
– C++ objects are allocated in the application's heap
– HWNDs are allocated in system resources
• A set of rules that prevent system resource or memory leaks
– Requires new and delete this for modeless dialogs (see
TN017: Destroying Window Objects)
C++ Russia, Moscow, 2015 27
Modeless dialogs in MFC
C++ Russia, Moscow, 2015 28
void CMainFrame::OnBnClickedCreate()
{
CMyDialog* pDialog = new CMyDialog;
pDialog->Create(IDD_MY_DIALOG, this);
pDialog->ShowWindow(SW_SHOW);
}
class CMyDialog : public CDialog
{
// ...
protected:
void CMyDialog::PostNcDestroy() override
{
CDialog::PostNcDestroy();
delete this;
}
// ...
};
Other memory management
• Qt
– Cross-platform application and UI framework
– QObject – base class, managing child-parent relationships
• Has a list of children, deletes them on destruction
• Has a pointer to parent, which may be null
• May change parent during the lifetime
– Requires explicit new and delete by design (see discussion)
C++ Russia, Moscow, 2015 29
Summary
• Same default rules for reference counting objects
• May require dedicated wrappers for some libraries,
like in MFC
• May not be applicable for specific memory
management techniques, like in Qt
C++ Russia, Moscow, 2015 30
Conclusion
• Good code is simple code
• “By default” principle to simplify things
• By default, raw delete is not used in C++ since it was
initially standardized
• Avoiding raw new works good in standard library;
declare this approach a default – for simplification
• If either new or delete is used, we assume that
– Situation requires special handling (and attention)
– Or specific memory management technique is used
C++ Russia, Moscow, 2015 31
C++ without new and delete
Questions?
Можно на русском :)
Bibliography
[McConnell2004] McConnell, Steve, and Detlef Johannis. Code
complete. Vol. 2. Redmond: Microsoft press, 2004.
[Wang2010] Wang, Rui, and Xuelei Qian. OpenSceneGraph 3.0:
Beginner's guide. Packt Publishing Ltd, 2010.
[Lavavej2012] Lavavej, Stephan. STL11: Magic && Secrets. Going
Native, 2012.
[Stroustrup2013] Stroustrup, Bjarne. A Tour of C++. Addison-Wesley,
2013.
[Stroustrup2014] Stroustrup, Bjarne. Make Simple Tasks Simple!
CppCon, 2014.
[Sutter2014] Sutter, Herb. Back to the Basics! Essentials of Modern C++
Style. CppCon, 2014.
[Meyers2014] Meyers, Scott. Effective Modern C++: 42 Specific Ways
to Improve Your Use of C++ 11 and C++ 14. "O'Reilly Media, Inc.", 2014.
C++ Russia, Moscow, 2015 33
QObject
• Use cases:
– Object is created on the stack
• Deleted once went out of scope
– Object is created in the heap with a parent
• Deleted by the parent
– Object is created in the heap without a parent
• Need to delete manually
• Or need to specify a parent manually
Матросов Михаил, С++ без new и delete,
Russian C++ User Group, Саратов, 2014
34
Qt::MakeChild
• Wrapper for safe use case
• Now new goes for unsafe case
• Drawback: cannot delay parent assignment
namespace Qt
{
template<class T, class... Args>
T* MakeChild(Args&&... args)
{
T* pObject = new T(std::forward<Args>(args)...);
Q_ASSERT(pObject->parent() != nullptr);
return pObject;
}
}
Матросов Михаил, С++ без new и delete,
Russian C++ User Group, Саратов, 2014
35
Qt::MakeChild
MyWidget::MyWidget()
{
// Safe, created on the stack
QProgressDialog progress("In progress...", "Cancel", 0, 100);
// Safe, parent is specified
{
// Regular, valid since C++98
QPushButton* pButton = new QPushButton("Push me", this);
// Proposed, modern C++ style
auto pButton2 = Qt::MakeChild<QPushButton>("And me", this);
}
// Unsafe, parent is null, need manual delete
m_pDialog = new QDialog();
}
Матросов Михаил, С++ без new и delete,
Russian C++ User Group, Саратов, 2014
36
CModelessDialog
C++ Russia, Moscow, 2015 37
class CModelessDialog : public CDialog {
protected:
using CDialog::CDialog;
void CModelessDialog::PostNcDestroy() override {
CDialog::PostNcDestroy();
delete this;
}
};
class CMyDialog : public CModelessDialog {
// ...
public:
static CMyDialog* CreateModeless(CWnd* pParent = nullptr) {
auto* pDialog = new CMyDialog;
pDialog->Create(IDD_MY_DIALOG, pParent);
pDialog->ShowWindow(SW_SHOW);
return pDialog;
}
protected:
CMyDialog() = default;
// ...
};

С++ without new and delete

  • 1.
    C++ without newand delete by Mikhail Matrosov mikhail.matrosov@gmail.com mmatrosov@aligntech.com
  • 2.
    Instead of contents •What? – Avoid new and delete in modern C++ • Why? – new and delete increase complexity • How? – std::make_shared, std::make_unique – Containers (STL, boost, libcds, etc.; or your own) – Wrappers for third-party smart pointers – Wrappers for libraries with specific memory management C++ Russia, Moscow, 2015 2
  • 3.
    Modern С++ • ModernС++ includes – С++14 features – Modern best practices • C++14 is officially released – ISO/IEC 14882:2014 / December 15, 2014 – Fully or partially supported by all major compilers C++ Russia, Moscow, 2015 3
  • 4.
    What & how? Managingmemory and objects from C to modern C++ C++ Russia, Moscow, 2015 4
  • 5.
    Objects in С typedefstruct ObjectTag { // Object members } Object; int InitObject(Object* io_pObject); int UseObject(Object* io_pObject); int ClearObject(Object* io_pObject); void ObjectsInC() { Object* pObject; pObject = malloc(sizeof(Object)); // Allocate memory InitObject(pObject); // Establish invariants and acquire resources UseObject(pObject); // Do the work ClearObject(pObject); // Release resources free(pObject); // Release memory // By the way: error handling :-/ } C++ Russia, Moscow, 2015 5
  • 6.
    Objects in С++ •Encapsulation: – Constructors – Destructors – Methods class Object { // Object members public: Object(); // Establish invariants and acquire resources ~Object(); // Release resources void Use(); // Do the work }; • Error handling: – Exceptions C++ Russia, Moscow, 2015 6
  • 7.
    new • Allocate memory •Initialize object in constructor delete • Deinitialize object in destructor • Free memory C++ Russia, Moscow, 2015 7 new creates a single object on the heap – Usually to share the object new[] creates a number of objects on the heap – Usually when number is known at runtime or is big enough
  • 8.
    Objects in С++ //1. Naive C++ style Object* p = new Object(); p->Use(); delete p; // 2. More secure C++98 with RAII std::auto_ptr<Object> ap(new Object()); ap->Use(); // 3. More secure C++11 with RAII std::unique_ptr<Object> up(new Object()); up->Use(); // 4. New bullet-proof modern C++ auto up2 = std::make_unique<Object>(); up2->Use(); C++ Russia, Moscow, 2015 8
  • 9.
    Shared objects inС++ void UseObject(Object*); // Shall only observe the object void AcceptObject(Object*); // Shall delete the object void ShareObject(std::shared_ptr<Object>); // May do both! // Naive C++ Object* p = new Object(); p->Use(); UseObject(p); // Preserve ownership p->Use(); AcceptObject(p); // Transfer ownership // C++98 & RAII /* No way standard to say this! */ // Modern C++ auto sp = std::make_shared<Object>(); sp->Use(); ShareObject(sp); // Share sp->Use(); ShareObject(std::move(sp)); // Share and discard ownership C++ Russia, Moscow, 2015 9
  • 10.
    Reference counting objectsin С++ // Naive C++ (not used) RefCounted* p = new RefCounted(); p->AddRef(); p->Use(); p->Release(); // C++98 & RAII RefPtr<RefCounted> rp = new RefCounted(); rp->Use(); // Modern C++ auto rp2 = MakeRefPtr<RefCounted>(); rp2->Use(); C++ Russia, Moscow, 2015 10
  • 11.
    Dynamic arrays inС++ void UseArray(int* ptr, int count); int n = 100; // Naive C++ int* p = new int[n]; UseArray(p, n); delete[] p; // C++98 & RAII std::vector<int> v(n); UseArray(&v[0], v.size()); // Modern C++ std::vector<int> v2(n); UseArray(v2.data(), v.size()); C++ Russia, Moscow, 2015 11
  • 12.
    Why? Advantages of makefunctions C++ Russia, Moscow, 2015 12
  • 13.
    Better == simple •A bit of authority: – Software's Primary Technical Imperative: Managing Complexity [McConnel2004] – Make Simple Tasks Simple! [Stroustrup2014] – ≈99.9998% developers are not experts [Sutter2014] – KISS principle (Keep It Simple, Stupid) • What is simple? – Keep simple things simple – Don’t make complex things unnecessarily complex – Write for clarity and correctness first, optimize later • How to keep it simple? – DRY principle (Don’t Repeat Yourself) – “By default” principle [Sutter2014] C++ Russia, Moscow, 2015 13
  • 14.
    “By default” principle •The main point: – Common task ⇔ common solution • Advantages: – Mutual understanding with other developers • Programs are parallelized in development-time too! – Easy for beginners – Less to think – productive laziness  – Same as for coding conventions • See also “A tour of C++” [Stroustrup2013] C++ Russia, Moscow, 2015 14
  • 15.
    std::make_unique<T>() vs. std::unique_ptr(new T) intGenerateId(); std::pair<std::unique_ptr<Object>, int> MakeObjectWithIdWrong() { return std::make_pair( std::unique_ptr<Object>(new Object()), GenerateId()); } std::pair<std::unique_ptr<Object>, int> MakeObjectWithIdRight() { return std::make_pair( std::make_unique<Object>(), // Safe GenerateId()); } DRY! C++ Russia, Moscow, 2015 15 // May throw! Exactly the same for std::shared_ptr and std::make_shared! // May leak!
  • 16.
    std::make_shared<T>() vs. std::shared_ptr(new T) std::shared_ptr<Object>sp(new Object()); counter Object sp Two memory allocations C++ Russia, Moscow, 2015 16
  • 17.
    std::make_shared<T>() vs. std::shared_ptr(new T) autosp = std::make_shared<Object>(); counter Object One memory allocation. We Know Where You Live optimization [Lavavej2012]. sp C++ Russia, Moscow, 2015 17
  • 18.
    Advantages of makefunctions • Both: – Exception safe – No type name duplication – Symmetry • std::make_shared: – Single memory allocation C++ Russia, Moscow, 2015 18
  • 19.
    std::make_shared and std::weak_ptr counterObject sp C++ Russia, Moscow, 2015 19 wp auto sp = std::make_shared<Object>(); std::weak_ptr<Object> wp = sp; sp.reset();
  • 20.
    When not touse make functions • Both: – Cannot specify custom deleters – Cannot pass braced initializer • std::unique_ptr: – Cannot specify custom allocator (for std::shared_ptr there is std::allocate_shared function) [see N3588, section IV.4] • std::shared_ptr: – Potential memory waste for long-living weak pointers – Works poorly with class-specific operators new&delete – Potential false sharing of the object and the reference counting block [see question on StackOverflow] • See also “Effective modern C++”, Item 21 [Meyers2014] C++ Russia, Moscow, 2015 20
  • 21.
    Summary • By default,raw delete is not used in C++ since RAII and standard containers • By default, raw new is not used in modern C++ within the standard library • If either is used, situation is not default and requires special handling (and, probably, special attention) C++ Russia, Moscow, 2015 21
  • 22.
    Beyond standard library Differentmemory management techniques in C++ C++ Russia, Moscow, 2015 22
  • 23.
    Memory management techniques •No memory management – Explicit new and delete – Not used in good code • Non-intrusive smart pointers – Applicable for all objects – Standard library • Intrusive smart pointers – Reference counting objects – Third-party libraries • Other – Parent to child relationships, coupling with system resources – Qt, MFC C++ Russia, Moscow, 2015 23
  • 24.
    Reference counting objects •OpenSceneGraph – Open source 3D framework written in C++ and OpenGL – osg::Referenced – base reference counting class • ref() increments counter • unref() decrements counter and deletes the object when counter drops to zero – osg::ref_ptr<T> – smart pointer • Calls ref() on construction • Calls unref() on destruction C++ Russia, Moscow, 2015 24
  • 25.
    OSG: C++ &RAII • Official code sample from [Wang2010, p. 78] • Perfect fit for upgrade – Can be done automatically osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array; // Init vertices osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array; // Init normals osg::ref_ptr<osg::Geometry> geom = new osg::Geometry; geom->setVertexArray(vertices.get()); geom->setNormalArray(normals.get()); // Further init geometry and use it C++ Russia, Moscow, 2015 25
  • 26.
    OSG: Modern C++ namespaceosg { template<typename T, typename... Args> osg::ref_ptr<T> make_ref(Args&&... args) { return new T(std::forward<Args>(args)...); } } auto vertices = osg::make_ref<osg::Vec3Array>(); // Init vertices auto normals = osg::make_ref<osg::Vec3Array>(); // Init normals auto geom = osg::make_ref<osg::Geometry>(); geom->setVertexArray(vertices.get()); geom->setNormalArray(normals.get()); // Further init geometry and use it C++ Russia, Moscow, 2015 26
  • 27.
    Other memory management •MFC (Microsoft Foundation Class) – C++ wrapper classes for Windows API – CWnd – base class for all windows objects • Represents both a C++ object and an HWND – C++ objects are allocated in the application's heap – HWNDs are allocated in system resources • A set of rules that prevent system resource or memory leaks – Requires new and delete this for modeless dialogs (see TN017: Destroying Window Objects) C++ Russia, Moscow, 2015 27
  • 28.
    Modeless dialogs inMFC C++ Russia, Moscow, 2015 28 void CMainFrame::OnBnClickedCreate() { CMyDialog* pDialog = new CMyDialog; pDialog->Create(IDD_MY_DIALOG, this); pDialog->ShowWindow(SW_SHOW); } class CMyDialog : public CDialog { // ... protected: void CMyDialog::PostNcDestroy() override { CDialog::PostNcDestroy(); delete this; } // ... };
  • 29.
    Other memory management •Qt – Cross-platform application and UI framework – QObject – base class, managing child-parent relationships • Has a list of children, deletes them on destruction • Has a pointer to parent, which may be null • May change parent during the lifetime – Requires explicit new and delete by design (see discussion) C++ Russia, Moscow, 2015 29
  • 30.
    Summary • Same defaultrules for reference counting objects • May require dedicated wrappers for some libraries, like in MFC • May not be applicable for specific memory management techniques, like in Qt C++ Russia, Moscow, 2015 30
  • 31.
    Conclusion • Good codeis simple code • “By default” principle to simplify things • By default, raw delete is not used in C++ since it was initially standardized • Avoiding raw new works good in standard library; declare this approach a default – for simplification • If either new or delete is used, we assume that – Situation requires special handling (and attention) – Or specific memory management technique is used C++ Russia, Moscow, 2015 31
  • 32.
    C++ without newand delete Questions? Можно на русском :)
  • 33.
    Bibliography [McConnell2004] McConnell, Steve,and Detlef Johannis. Code complete. Vol. 2. Redmond: Microsoft press, 2004. [Wang2010] Wang, Rui, and Xuelei Qian. OpenSceneGraph 3.0: Beginner's guide. Packt Publishing Ltd, 2010. [Lavavej2012] Lavavej, Stephan. STL11: Magic && Secrets. Going Native, 2012. [Stroustrup2013] Stroustrup, Bjarne. A Tour of C++. Addison-Wesley, 2013. [Stroustrup2014] Stroustrup, Bjarne. Make Simple Tasks Simple! CppCon, 2014. [Sutter2014] Sutter, Herb. Back to the Basics! Essentials of Modern C++ Style. CppCon, 2014. [Meyers2014] Meyers, Scott. Effective Modern C++: 42 Specific Ways to Improve Your Use of C++ 11 and C++ 14. "O'Reilly Media, Inc.", 2014. C++ Russia, Moscow, 2015 33
  • 34.
    QObject • Use cases: –Object is created on the stack • Deleted once went out of scope – Object is created in the heap with a parent • Deleted by the parent – Object is created in the heap without a parent • Need to delete manually • Or need to specify a parent manually Матросов Михаил, С++ без new и delete, Russian C++ User Group, Саратов, 2014 34
  • 35.
    Qt::MakeChild • Wrapper forsafe use case • Now new goes for unsafe case • Drawback: cannot delay parent assignment namespace Qt { template<class T, class... Args> T* MakeChild(Args&&... args) { T* pObject = new T(std::forward<Args>(args)...); Q_ASSERT(pObject->parent() != nullptr); return pObject; } } Матросов Михаил, С++ без new и delete, Russian C++ User Group, Саратов, 2014 35
  • 36.
    Qt::MakeChild MyWidget::MyWidget() { // Safe, createdon the stack QProgressDialog progress("In progress...", "Cancel", 0, 100); // Safe, parent is specified { // Regular, valid since C++98 QPushButton* pButton = new QPushButton("Push me", this); // Proposed, modern C++ style auto pButton2 = Qt::MakeChild<QPushButton>("And me", this); } // Unsafe, parent is null, need manual delete m_pDialog = new QDialog(); } Матросов Михаил, С++ без new и delete, Russian C++ User Group, Саратов, 2014 36
  • 37.
    CModelessDialog C++ Russia, Moscow,2015 37 class CModelessDialog : public CDialog { protected: using CDialog::CDialog; void CModelessDialog::PostNcDestroy() override { CDialog::PostNcDestroy(); delete this; } }; class CMyDialog : public CModelessDialog { // ... public: static CMyDialog* CreateModeless(CWnd* pParent = nullptr) { auto* pDialog = new CMyDialog; pDialog->Create(IDD_MY_DIALOG, pParent); pDialog->ShowWindow(SW_SHOW); return pDialog; } protected: CMyDialog() = default; // ... };