[英]Create reference to object in unique_ptr with typecast
I find I still do an embarrassingly large number of things in c style, so I am now trying to embrace the new millennium by reducing my usage of raw pointers. 我发现我仍然用c风格做大量令人尴尬的事情,因此我现在正尝试通过减少对原始指针的使用来迎接新的千年。 I have a vector of
unique_ptr<BaseClass>
, that each points to an object of a derived class. 我有一个
unique_ptr<BaseClass>
向量,每个向量都指向派生类的对象。 I am trying to get a nice way to refer to one of the objects of the derived class. 我试图获得一种很好的方法来引用派生类的对象之一。 At the moment, I do this by using the
.get()
function and casting this to the derived class. 目前,我通过使用
.get()
函数并将其转换为派生类来实现。
However, as I understand it, .get()
is mostly there to interface with legacy code that insists on raw pointers, and its use should be avoided. 但是,据我了解,
.get()
大部分用于与坚持使用原始指针的旧代码进行接口,因此应避免使用它。 Having another pointer to an object within a unique_ptr
doesn't seem like great style if it can be avoided. 如果可以避免的话,在
unique_ptr
中拥有另一个指向对象的指针似乎不是很棒的样式。 Is there a way to get a reference to the derived class object, without using get? 有没有一种方法可以在不使用get的情况下获取对派生类对象的引用? Or some other convenient way of handling the object?
还是一些其他方便的方式来处理对象?
Here is a simplified code example: 这是一个简化的代码示例:
#include <iostream>
#include <vector>
class Fruit {
public:
double size = 0;
virtual ~Fruit() = default;
};
class Apple : public Fruit {
public:
bool hasLeaf = false;
};
void doAppleStuff(std::vector<std::unique_ptr<Fruit> > &apples) {
// assume we know that element [0] exists and it is definitely of type Apple
auto apple = static_cast<Apple *> (apples[0].get()); // is there a better option?
if (apple->hasLeaf) {
std::cout << "We can leaf now" << std::endl;
} else {
std::cout << "We are pitiably leafless" << std::endl;
}
}
int main() {
std::vector<std::unique_ptr<Fruit> > fruitVec;
auto apple = new Apple;
apple->hasLeaf = true;
std::unique_ptr<Fruit> applePt(apple);
fruitVec.push_back(std::move(applePt));
doAppleStuff(fruitVec);
return 0;
}
(I think that it's probably possible to shorten the main function with make_unique
from c++14). (我认为使用c ++ 14中的
make_unique
可能会缩短main函数)。
Would it be good coding style to do something like this? 做这样的事情会是好的编码风格吗?
auto &apple = *static_cast<Apple *> (apples[0].get());
The answer at "Downcasting" unique_ptr<Base> to unique_ptr<Derived> outlines a method to "cast" the unique_ptr
by releasing it and recreating a new unique_ptr
to the derived class, but that doesn't seem applicable here, as I don't really want to mess with the vector of unique pointers (unless I am missing something). 将“ unicast_ptr <基本>“向下转换”到unique_ptr <Derived>的答案概述了一种方法,该方法通过释放它并为派生类重新创建一个新的
unique_ptr
来“铸造” unique_ptr
,但这似乎不适用于这里,因为我没有我真的很想弄乱唯一指针的向量(除非我错过了什么)。
If you know that the pointer is non- nullptr
, a simpler cast is: 如果您知道指针为非
nullptr
, nullptr
简单的转换为:
auto& apple = static_cast<Apple&>(*apples[0]);
This syntax works with all smart-pointers that support T& operator*() const
(eg std::unique_ptr
, std::shared_ptr
, boost::intrusive_ptr
). 此语法适用于所有支持
T& operator*() const
智能指针(例如std::unique_ptr
, std::shared_ptr
, boost::intrusive_ptr
)。
In cases with multiple inheritance casting from-base-reference-to-derived-reference is faster than casting from-base-pointer-to-derived-pointer because the latter must always check for nullptr
before adding or subtracting an offset to the pointer (so that nullptr
turns into nullptr
after the cast), whereas references cannot be nullptr
and therefore no run-time check is necessary. 在具有多重继承的情况下, 从基础引用到源引用的转换比从基础指针到源指针的转换更快,因为后者必须在添加或减去指针的偏移量之前始终检查
nullptr
(因此nullptr
在nullptr
转换后变成nullptr
),而引用不能为nullptr
,因此不需要运行时检查。
A safer alternative is to define a helper function 一个更安全的选择是定义一个辅助函数
template <typename T> //
std::vector<T *> of_type(const std::vector<std::unique_ptr<Fruit>> & fruits) {
std::vector<T *> result;
for (auto & ptr : fruits) {
if (T * item = dynamic_cast<T *>(ptr.get())) {
result.push_back(item);
}
}
return result;
}
and then change doAppleStuff
to 然后将
doAppleStuff
更改为
void doAppleStuff(std::vector<Apple *> & apples);
called as 称为
doAppleStuff(as_type<Apple>(fruitVec));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.