官术网_书友最值得收藏!

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:

主站蜘蛛池模板: 晋江市| 石阡县| 海伦市| 台江县| 乌鲁木齐县| 孟津县| 钟祥市| 河南省| 浦城县| 乃东县| 疏附县| 西华县| 兰坪| 石林| 鹿邑县| 玛多县| 富源县| 桃园市| 台北县| 普陀区| 平原县| 英德市| 蒙山县| 宁夏| 叙永县| 探索| 图片| 重庆市| 泸水县| 博野县| 佳木斯市| 大洼县| 兴海县| 浏阳市| 大宁县| 鹰潭市| 梓潼县| 阿拉善右旗| 张家口市| 甘洛县| 德江县|