c++ - 如何使用 unique_ptr 将 const 指针传递给 const 对象

标签 c++ c++11 unique-ptr

我想通过 unique_ptr到辅助函数,我想确保辅助函数既不修改指针,也不修改指向的对象。没有 unique_ptr ,解决办法是有

void takePtr(AClass const * const aPtr) {
  // Do something with *aPtr. 
  // We cannot change aPtr, not *aPtr. 
}

(嗯,从技术上讲,AClass const * aPtr 就足够了。)我可以用

来调用它
AClass * aPtr2 = new AClass(3);
takePtr(aPtr2);

我想改用 unique_ptr ,但不知道怎么写。我试过了

void takeUniquePtr(unique_ptr<AClass const> const & aPtr) {
  // Access *aPtr, but should not be able to change aPtr, or *aPtr. 
}

当我用

调用它时
unique_ptr<AClass> aPtr(new AClass(3));
takeUniquePtr(aPtr);

它不编译。我看到的错误是

testcpp/hello_world.cpp:141:21: error: invalid user-defined conversion from ‘std::unique_ptr<AClass>’ to ‘const std::unique_ptr<const AClass>&’ [-fpermissive]

不应该从 unique_ptr<AClass> 转换至unique_ptr<AClass const>是自动的?我在这里想念什么?

顺便说一句,如果我更改 unique_ptr<AClass const> const & aPtrunique_ptr<AClass> const & aPtr在函数定义中,它可以编译,但是我可以调用像 aPtr->changeAClass() 这样的函数,我不想允许。

最佳答案

智能指针用于管理所有权和生命周期,它们允许我们(除其他外)安全地转移代码各个部分的所有权。

当您通过 const unique_ptr<T>&对于一个函数(与 T 是否为 const 无关),它实际上意味着该函数 promise 永远不会修改 unique_ptr本身(但如果 T 不是 const ,它仍然可以修改指向的对象)即。不会有任何可能的所有权转让。您只是在使用 unique_ptr作为裸指针的无用包装器。

因此,正如@MarshallClow 在评论中建议的那样,您应该摆脱包装器并传递裸指针或直接引用。这样做的好处是您的代码现在语义清晰(您的函数签名清楚地表明它不会与所有权混淆,这在 const unique_ptr<...>&立即显而易见。 ) 它同时解决了你的“约束”问题!

即:

void someFunction(const AClass* p) { ... }

std::unique_ptr<AClass> ptr(new AClass());
someFunction(ptr.get());

编辑:解决您的第二个问题“为什么编译器不让我...将 unique_ptr<A> 转换为 unique_ptr<A const>”。

其实你可以移动一个unique_ptr<A>unique_ptr<A const> :

std::unique_ptr<A> p(new A());
std::unique_ptr<const A> q(std::move(p));

但正如您所见,这意味着所有权从 p 转移。至q .

您的代码的问题在于您传递了一个(引用)unique_ptr<const A> 到一个函数。由于与 unique_ptr<A> 存在类型差异,要使其工作,编译器需要实例化一个临时的。但除非您使用 std::move 手动转移所有权,编译器将尝试复制您的unique_ptr它不能这样做,因为 unique_ptr明确禁止。

请注意,如果您移动 unique_ptr,问题会如何消失:

void test(const std::unique_ptr<const int>& p) { ... }

std::unique_ptr<int> p(new int(3));
test(std::move(p));

编译器现在可以构造一个临时的 unique_ptr<const A>并移动原 unique_ptr<A>不辜负您的期望(因为现在很明显您想要移动,而不是复制)。

所以,问题的根源在于 unique_ptr只有移动语义没有复制语义,但您需要复制语义来创建一个临时的,然后保留所有权。 Egg and chicken, unique_ptr只是不是这样设计的。

如果您现在考虑 shared_ptr 复制语义,问题也就消失了。

void test(const std::shared_ptr<const int>& p) { ... }

std::shared_ptr<int> p(new int(3));
test(p);
//^^^^^ Works!

原因是编译器现在可以创建一个临时的 std::shared_ptr<const int> 复制(从 std::shared_ptr<int> 自动转换)并将临时绑定(bind)到 const引用。

我想这或多或少涵盖了它,尽管我的解释缺乏标准术语并且可能没有应有的清晰。 :)

关于c++ - 如何使用 unique_ptr 将 const 指针传递给 const 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16425345/

相关文章:

c++ - std::unique_ptr 是 RAII 的应用吗?

c++ - std::function 类型和模板实例化

c++ - 如何让 g_print() 出现?

c++ - Windows Hook 和 DLL 加载

c++ - 类成员容器迭代器在成员函数 std::find 中不兼容,但为什么不呢?

c++ - unique_ptr - 无效指针和段错误

Java程序通过调用C代码实现矩阵相乘

c++ - boost::date_time 和 std::chrono 之间的互操作性

c++ - 在带有 boost::function 的 std::for_each 中使用 boost.lambda

c++ - 为什么 std::unique_ptr 重置与赋值不同?