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

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:

主站蜘蛛池模板: 贵定县| 昌吉市| 和静县| 岱山县| 栾城县| 彭泽县| 舞钢市| 宝清县| 平舆县| 泽库县| 都匀市| 庄河市| 莱州市| 阳新县| 凤山市| 兴宁市| 绿春县| 河曲县| 永平县| 资阳市| 新建县| 珠海市| 梨树县| 霍林郭勒市| 新竹县| 兴山县| 灯塔市| 鄂托克旗| 阿图什市| 舞钢市| 竹山县| 白朗县| 讷河市| 安多县| 沭阳县| 德惠市| 永宁县| 齐河县| 安丘市| 积石山| 永川市|