std::unique_ptr 在推送到 std::vector 时的正确用法是什么?

What is the correct usage of std::unique_ptr while pushing into std::vector

本文关键字:std 用法 是什么 unique ptr vector      更新时间:2023-10-16

我想在我的类中有一个指向对象的指针向量。为了避免为它制作析构函数,我想使用 std::unique_ptr ,因为对象是在我的类中创建/拥有/销毁的,但我有一个无法理解的编译器错误。下一个代码将作为我问题的简短示例:

std::unique_ptr<int> createPtr(int value)
{
    std::unique_ptr<int> ptr(new int(value));
    return ptr;
};
int main()
{
    std::vector<std::unique_ptr<int>> vec;
    vec.push_back(createPtr(1));
    std::unique_ptr<int> ptr = createPtr(2);
    vec.push_back(ptr);//error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>'
}

你能解释一下为什么我会收到这个错误以及std::unique_ptr的正确用法是什么?

要么:

vec.push_back(std::move(ptr));

或:

vec.emplace_back(createPtr(2));

考虑vec.push_back()。它有两个重载,需要const std::unique_ptr<int>&std::unique_ptr<int>&&。第一次重载永远不能使用。这是因为vector<>要求类型是可分配的或可移动的(C++11 加法)。"可分配性"意味着复制。 push_back(const T&)将尝试将传入的值复制(分配)到容器末尾的新空间。 std::unique_ptr<>表示由单个所有者拥有的资源。通过复制它(指针),将存在多个所有者。因此unique_ptr是不可复制的。

说了这么多,你只能使用T&&重载。

createPtr()返回std::unique_ptr<int>,但由于这是一个临时结果(函数返回值),它被认为是一个右值引用(隐式)。这就是为什么可以使用它的原因。

ptr只是一个std::unique_ptr<int>,它是一个左值引用(无论你是否在它旁边加上&&,因为命名的右值仍然被视为左值)。左值永远不会隐式转换为右值(完全不安全)。但是你基本上可以通过使用 std::move() 告诉编译器"好的,你可以接受我传递给你的对象,我保证我不会期望参数保持不变"。

您有一个unique_ptr

std::unique_ptr<int> ptr = createPtr(2);

现在你把它的副本放在向量中:

vec.push_back(ptr);

现在,您有两个具有相同值的unique_ptr。 如果允许这样做,它就不是唯一的。