我开始使用c ++ 11功能,我喜欢使用智能指针只拥有对象.这是我的班级:
class MyClass {
public:
vector<MyObject*> get_objs() const;
private:
vector<unique_ptr<MyObject>> m_objs;
};
Run Code Online (Sandbox Code Playgroud)
语义是MyClass拥有一系列MyObject通过make_unique()创建的.get_objs()返回原始指针的向量,以便各种调用者更新对象.因为那些调用者不拥有对象,所以函数不返回vector<unique_ptr>.
但这意味着我需要get_objs()像这样实现:
vector<MyObjects*> MyClass::get_objs() const
{
vector<MyObjects*> ret;
for (auto obj : my_objs) {
ret.push_back(obj->get());
}
return ret;
}
Run Code Online (Sandbox Code Playgroud)
get_objs()每次有一个开销来构造这个原始指针向量时,我会经常调用我的问题.
我能在这做些什么吗?如果没有c ++ 11技巧来节省开销,我应该首先使用type vector<MyObject*>for m_objs?
UPDATE 1
Run Code Online (Sandbox Code Playgroud)
使用Jonathan Wakely的解决方案operator[]改进了我的解决方案,以便调用者可以直接访问单个对象.
还有其他解决方案吗?我不介意去所有的地方打电话,get_objs(),但想看看是否有更好的解决方案.
另一个注意事项 - 我不能使用BOOST,只是我必须忍受的一些限制.
首先,您可以使用ret.reserve(m_objs.size())预分配正确数量的元素.
或者,不要为调用者返回一个向量直接迭代的向量,而是公开类似向量的接口:
class MyClass {
public:
struct iterator;
iterator begin();
iterator end();
MyObject* operator[](size_t n) { return m_objs[n].get(); }
private:
vector<unique_ptr<MyObject>> m_objs;
};
Run Code Online (Sandbox Code Playgroud)
这允许调用者直接修改对象,而不是获取指针容器.
class MyClass {
public:
std::vector<std::unique_ptr<MyObject>> const& get_objs() const {
return m_objs;
}
private:
std::vector<std::unique_ptr<MyObject>> m_objs;
};
Run Code Online (Sandbox Code Playgroud)
aconst std::unique_ptr<MyObject>&不能窃取所有权,并且与 a 不同std::unique_ptr<const MyObject>。Aconst std::vector<std::unique_ptr<MyObject>>&只能授予const对其数据的访问权限。
在c++20 中,我会这样做:
class MyClass {
public:
std::span<std::unique_ptr<MyObject> const> get_objs() const {
return {m_objs.begin(), m_objs.end()};
}
private:
std::vector<std::unique_ptr<MyObject>> m_objs;
};
Run Code Online (Sandbox Code Playgroud)
它隐藏了“我将它存储在一个向量中”的实现细节,同时暴露了“我正在连续存储它”。
在c++20之前,span如果您有预算,我建议您找到或编写自己的类型。它们非常有用。