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

Does this use of std::make_unique lead to non-unique 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.

请公开情况。

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

你传递了Some&作为参数,这里调用了拷贝构造函数,构造了新的对象。

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

它们不指向 相同的 资源,它们各自指向它的不同 copy。你可以通过删除复制构造函数来说明它看到错误:

#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;
}

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

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

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

附录:正如 Remy Lebeau 所指出的,从 C++11 开始,建议使用 std::addressof 函数用于此目的,即使重载 & 运算符,它也能获取对象的实际地址:

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

both p1 and p2 point to the same instance 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