C++:Microsoft的ComPtr和c++中的unique_ptr、shared_ptr有什么区别?

3

我看到这些项目中混合使用了指针类。

有时他们使用std:unique_ptr、shared_ptr,有时则使用Microsoft::WRL::ComPtr。

只是想知道它们之间的区别以及如何确定使用哪个?


建议您始终使用 unique_ptrshared_ptr,这样您的软件在平台之间更具可移植性并且可能依赖于更少的外部库。 - RamblingMad
1个回答

4

std::unique_ptr 表示一个指向对象的 独占 指针,即你不能复制这个指针;但你仍然可以移动这个指针。

例如:

auto ptr = std::make_unique<float>(5.0f);
std::unique_ptr other_ptr = ptr;

代码无法编译,但是

auto ptr = std::make_unique<float>(5.0f);
std::unique_ptr other_ptr = std::move(ptr);

将使用std::shared_ptr表示一个可以被多个其他shared_ptr指向的对象的指针。它可以被复制和移动。

你不会总是使用shared_ptr而不是unique_ptr的原因是,在构建和销毁时,shared_ptr会比较慢,并且每当需要将其传递到函数中时,您可能会遇到这种缓慢的(解)构造过程。

例如:

auto ptr = std::make_shared<float>(5.0f);
std::shared_ptr other_ptr = ptr;

相对于将原始指针移动到新指针中,使用shared_ptr会慢得多(可能很多),因为编译器必须跟踪有多少shared_ptr实例指向该对象,以便当shared_ptr被析构时,如果它是指向该对象的最后一个指针,则会删除它。


至于ComPtr……除非绝对必要,否则请不要使用它。这几乎从来不需要。你可能看到在你所提到的项目中使用它的原因是某些Microsoft特定的API使用它,这是你必须使用它的那些时候之一。


编辑

为了展示这些不同智能指针的优缺点以及何时应选择它们,需要一个体面的示例程序。所以这里有一个!

void f(std::unique_ptr<float> p){}
void f(std::shared_ptr<float> p){}

void g(std::unique_ptr<float> &p){}
void g(std::shared_ptr<float> &p){}

int main(int argc, char *argv[]){
    auto uptr = std::make_unique<float>(6.9f);
    auto sptr = std::make_shared<float>(4.20f);

    // f(uptr);
    // error, trying to make a copy of a unique_ptr

    f(sptr);
    // fine, shared_ptr may be copied

    f(std::make_unique<float>(6.9f));
    f(std::make_shared<float>(4.20f));
    // both fine, value initialized in function call and moved into function.

    g(uptr);
    g(sptr);
    // both fine, shared and unique pointers may be passed by reference
    // as no copy or move is made.
}

哦,我明白了,这是否意味着我不能将unique_ptr作为函数参数? - William Fleurant
不是,但有点像。这意味着您无法将 unique_ptr 按值传递到函数中。 所以如果您传入现有的 unique_ptr,则 void f(unique_ptr p) 将无法编译,但任何类型的引用或指针都可以正常工作。 - RamblingMad
你可以在函数中使用unique_ptr值参数,只需要调用者传递一个值唯一指针(从另一个函数返回或在调用中构造),或std::move一个现有的unique_ptr。这对于期望拥有对象所有权的函数来说是一个好的模式。 - Thief

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接