这种std :: make_unique的使用会导致非唯一指针吗?

时间:2016-12-01 13:07:39

标签: c++ smart-pointers

假设我在C ++中有以下代码:

#include <memory>
#include <iostream>

struct Some {
        Some(int _a) : a(_a) {}
        int a;
};

int main() {
        Some some(5);

        std::unique_ptr<Some> p1 = std::make_unique<Some>(some);
        std::unique_ptr<Some> p2 = std::make_unique<Some>(some);

        std::cout << p1->a << " " << p2->a << std::endl;
        return 0;
}

据我所知,使用唯一指针来保证资源不被共享。但在这种情况下,p1p2都指向同一个实例some

请揭开情况。

4 个答案:

答案 0 :(得分:26)

他们没有指向相同的资源,他们每个都指向不同的副本。您可以通过删除复制构造函数来说明错误:

#include <memory>
#include <iostream>

struct Some {
        Some(int _a) : a(_a) {}
        Some(Some const&) = delete;
        int a;
};

int main() {
        Some some(5);

        std::unique_ptr<Some> p1 = std::make_unique<Some>(some); //error here
        std::unique_ptr<Some> p2 = std::make_unique<Some>(some);

        std::cout << p1->a << " " << p2->a << std::endl;
        return 0;
}

答案 1 :(得分:16)

std::make_unique创建对象,使用指定的参数调用构造函数。

您传递Some&作为参数,此处调用了复制构造函数,并构造了新对象。

所以,p1和p2是两个完全不同的指针,但是使用复制构造函数从同一个对象构造

答案 2 :(得分:9)

  

p1p2都指向同一个实例some

No, they don't.

#include <memory>
#include <iostream>

struct Some {
        Some(int _a) : a(_a) {}
        int a;
};

int main() {
        Some some(5);

        std::unique_ptr<Some> p1 = std::make_unique<Some>(some);
        std::unique_ptr<Some> p2 = std::make_unique<Some>(some);

        std::cout << p1->a << " " << p2->a << std::endl;
        p1->a = 42;
        std::cout << p1->a << " " << p2->a << std::endl;
        return 0;
}

输出:

5 5
42 5

答案 3 :(得分:1)

要测试两个指针是否指向同一个对象实例,您应该比较它们指向的位置,而不是对象成员变量:

std::cout << &(*p1) << " " << &(*p2) << std::endl;

这将表明他们确实指向同一个实例。

ADDENDUM:正如Remy Lebeau所指出的那样,从C ++ 11开始,建议使用 std::addressof用于此目的,即使&运算符过载,也会获取对象的实际地址:

std::cout << std::addressof(*p1) << " " << std::addressof(*p2) << std::endl;