Yog*_*rma 20 c++ unique-ptr c++11
我想传递一个unique_ptr
辅助函数,我想确保辅助函数既不修改指针也不修改指针对象.如果没有unique_ptr
,解决方案就是拥有
void takePtr(AClass const * const aPtr) {
// Do something with *aPtr.
// We cannot change aPtr, not *aPtr.
}
Run Code Online (Sandbox Code Playgroud)
(从技术上讲,这AClass const * aPtr
已经足够了.)我可以这样说
AClass * aPtr2 = new AClass(3);
takePtr(aPtr2);
Run Code Online (Sandbox Code Playgroud)
我想反而使用unique_ptr
,但无法弄清楚如何写这个.我试过了
void takeUniquePtr(unique_ptr<AClass const> const & aPtr) {
// Access *aPtr, but should not be able to change aPtr, or *aPtr.
}
Run Code Online (Sandbox Code Playgroud)
当我打电话给这个时
unique_ptr<AClass> aPtr(new AClass(3));
takeUniquePtr(aPtr);
Run Code Online (Sandbox Code Playgroud)
它没有编译.我看到的错误是
testcpp/hello_world.cpp:141:21: error: invalid user-defined conversion from ‘std::unique_ptr<AClass>’ to ‘const std::unique_ptr<const AClass>&’ [-fpermissive]
Run Code Online (Sandbox Code Playgroud)
转换不unique_ptr<AClass>
应该unique_ptr<AClass const>
是自动的吗?我在这里错过了什么?
顺便说一句,如果我改变unique_ptr<AClass const> const & aPtr
对unique_ptr<AClass> const & aPtr
函数定义,它编译,但我可以调用类的函数aPtr->changeAClass()
,这是我不希望允许.
sya*_*yam 29
智能指针用于管理所有权和生命周期,它们允许我们(除其他事项外)安全地转移代码各部分的所有权.
当你传递一个const unique_ptr<T>&
给函数(无关是否T
是const
与否),它实际上意味着函数承诺从未改变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());
Run Code Online (Sandbox Code Playgroud)
编辑:解决您的次要问题:" 你为什么不编译器让我...投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));
Run Code Online (Sandbox Code Playgroud)
但正如你所看到的,这意味着所有权从转移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));
Run Code Online (Sandbox Code Playgroud)
编译器现在能够构建一个临时的unique_ptr<const A>
并移动原始unique_ptr<A>
而不会破坏您的期望(因为现在很清楚您想移动,而不是复制).
所以,问题的根源在于unique_ptr
只有移动语义而不是复制语义,但是你需要复制语义来创建一个临时的,然后保持所有权.鸡蛋和鸡肉,unique_ptr
只是不是这样设计的.
如果您现在考虑shared_ptr
哪个具有复制语义,问题也会消失.
void test(const std::shared_ptr<const int>& p) { ... }
std::shared_ptr<int> p(new int(3));
test(p);
//^^^^^ Works!
Run Code Online (Sandbox Code Playgroud)
原因是编译器现在能够创建临时std::shared_ptr<const int>
副本(自动从中转换std::shared_ptr<int>
)并将该临时绑定到const
引用.
我想这或多或少涵盖了它,即使我的解释缺乏标准术语,也许不是应该如此清晰.:)