- Learning C++ Functional Programming
- Wisnu Anggoro
- 344字
- 2021-07-02 20:51:38
Replacing a raw pointer using unique_ptr
The next pointer we will see is the unique_ptr pointer. It is fast, efficient, and a near drop-in replacement for raw or naked pointers. It provides exclusive ownership semantics, which exclusively owns the object that it points to. By its exclusiveness, it can destroy the object when its destructor is called if it has a non-null pointer. It also cannot be copied due to its exclusiveness. It has no copy constructor and copy assignment. Although it cannot be copied, it can be moved since it provides a move constructor and a move assignment.
These are the methods we can use to construct unique_ptr:
auto up1 = unique_ptr<int>{};
auto up2 = unique_ptr<int>{ nullptr };
auto up3 = unique_ptr<int>{ new int { 1234 } };
Based on the preceding code, up1 and up2 will construct two new unique_ptr that point to nothing (null), whereas up3 will point to the address that holds the 1234 value. However, C++14 adds a new library function to construct unique_ptr, that is, make_unique. So, we can construct a new unique_ptr pointer as follows:
auto up4 = make_unique<int>(1234);
The up4 variable will also point to the address that holds the 1234 value.
Now, let's take a look at the following block of code:
/* unique_ptr_1.cpp */
#include <memory>
#include <iostream>
using namespace std;
struct BodyMass
{
int Id;
float Weight;
BodyMass(int id, float weight) :
Id(id),
Weight(weight)
{
cout << "BodyMass is constructed!" << endl;
cout << "Id = " << Id << endl;
cout << "Weight = " << Weight << endl;
}
~BodyMass()
{
cout << "BodyMass is destructed!" << endl;
}
};
auto main() -> int
{
cout << "[unique_ptr_1.cpp]" << endl;
auto myWeight = make_unique<BodyMass>(1, 165.3f);
cout << endl << "Doing something!!!" << endl << endl;
return 0;
}
We try to construct a new unique_ptr pointer that points to the address that holds a BodyMass data type. In BodyMass, we have a constructor as well as a destructor. Now, let's see how the unique_ptr pointer works by running the preceding code. The output we get on the screen should be like the following screenshot:

As we can see in the preceding screenshot, the constructor is invoked when we construct unique_ptr. Moreover, unlike the traditional C++ language, where we have to free the memory up when we use a pointer, in modern C++, the memory will be freed up automatically when it is out of scope. We can see that the destructor of BodyMass is invoked when the program exits, which means myWeight is out of scope.
Now, let's test the exclusiveness of unique_ptr by analyzing the following code snippet:
/* unique_ptr_2.cpp */
#include <memory>
#include <iostream>
using namespace std;
struct BodyMass
{
int Id;
float Weight;
BodyMass(int id, float weight) :
Id(id),
Weight(weight)
{
cout << "BodyMass is constructed!" << endl;
cout << "Id = " << Id << endl;
cout << "Weight = " << Weight << endl;
}
BodyMass(const BodyMass &other) :
Id(other.Id),
Weight(other.Weight)
{
cout << "BodyMass is copy constructed!" << endl;
cout << "Id = " << Id << endl;
cout << "Weight = " << Weight << endl;
}
~BodyMass()
{
cout << "BodyMass is destructed!" << endl;
}
};
auto main() -> int
{
cout << "[unique_ptr_2.cpp]" << endl;
auto myWeight = make_unique<BodyMass>(1, 165.3f);
// The compiler will forbid to create another pointer
// that points to the same allocated memory/object
// since it's unique pointer
//auto myWeight2 = myWeight;
// However, we can do the following expression
// since it actually copies the object that has been allocated
// (not the unique_pointer)
auto copyWeight = *myWeight;
return 0;
}
As we can see in the preceding code, we see that we can't assign the unique_ptr instance to another pointer since it will break the exclusiveness of unique_ptr. The compiler will throw an error if we make the following expression:
auto myWeight2 = myWeight;
However, we can assign the value of the unique_ptr to another object since it has been allocated. To prove it, we have added a copy constructor to log when the following expression is executed:
auto copyWeight = *myWeight;
If we run the preceding unique_ptr_2.cpp code, we will see the following output on the screen:

As we can see in the preceding screenshot, the copy constructor is called when the copy assignment is executed. It proves that we can copy the value of the unique_ptr object but not the object itself.
As we discussed earlier, unique_ptr has moved the constructor, although it has no copy constructor. The use of this construction can be found in the following piece of code:
/* unique_ptr_3.cpp */
#include <memory>
#include <iostream>
using namespace std;
struct BodyMass
{
int Id;
float Weight;
BodyMass(int id, float weight) :
Id(id),
Weight(weight)
{
cout << "BodyMass is constructed!" << endl;
cout << "Id = " << Id << endl;
cout << "Weight = " << Weight << endl;
}
~BodyMass()
{
cout << "BodyMass is destructed!" << endl;
}
};
unique_ptr<BodyMass> GetBodyMass()
{
return make_unique<BodyMass>(1, 165.3f);
}
unique_ptr<BodyMass> UpdateBodyMass(
unique_ptr<BodyMass> bodyMass)
{
bodyMass->Weight += 1.0f;
return bodyMass;
}
auto main() -> int
{
cout << "[unique_ptr_3.cpp]" << endl;
auto myWeight = GetBodyMass();
cout << "Current weight = " << myWeight->Weight << endl;
myWeight = UpdateBodyMass(move(myWeight));
cout << "Updated weight = " << myWeight->Weight << endl;
return 0;
}
In the preceding code, we have two new functions--GetBodyMass() and UpdateBodyMass(). We construct a new unique_ptr object from the GetBodyMass() function, then we update the value of its Weight using the UpdateBodyMass() function. We can see that we use the move function when we pass an argument to the UpdateBodyMass() function. It's because unique_ptr has no copy constructor, and it has to be moved in order to update the value of its property. The screen output of the preceding code is as follows:

- Mobile Application Development:JavaScript Frameworks
- Mastering ServiceStack
- Mastering Entity Framework
- 教孩子學編程:C++入門圖解
- 深度學習:算法入門與Keras編程實踐
- SQL基礎教程(視頻教學版)
- C程序設計案例教程
- 零基礎學Python網絡爬蟲案例實戰全流程詳解(高級進階篇)
- Learning Laravel's Eloquent
- JSP程序設計實例教程(第2版)
- 鴻蒙OS應用編程實戰
- 區塊鏈項目開發指南
- QPanda量子計算編程
- Practical Microservices
- INSTANT Apache ServiceMix How-to