堆分配的对象是否存在永不为空的唯一所有者?
Is there a never-null unique owner of heap allocated objects?
目前,我正在存储一个std::unique_ptr
集合来堆多态类型的分配对象:
struct Foo {
virtual ~Foo() = default;
};
Collection<std::unique_ptr<Foo>> foos;
我需要的基本界面是将Foo
的所有者放入/从foos
.存储在foos
中的对象永远不应该被nullptr
所以我想用编译时检查替换运行时assert(owner_taken)
。此外,我希望能够在可能预期可为空的上下文中使用非空所有者。
也许,我需要存储类似unique_ref
的东西,但是我如何从foos
中提取一个?我不想要副本,我想要存储的对象本身,所以owner->clone()
不是解决方案。我也不能std::move(owner)
,因为"唯一引用"的状态之后将无效。
是否有一个干净的设计决策?
堆分配的对象是否存在永不为空的唯一所有者?
标准库中没有这种类型。
可以实现这种类型。只需定义一个带有unique_ptr成员的类型,并将默认构造函数标记为已删除。您也可以将构造函数标记为std::nullptr_t
删除,以便在编译时阻止从nullptr
构造。
无论是从外部指针构造,还是在构造函数中分配,都无法在运行时检查 null。
阅读您的问题,我解释以下要求:
- 您不想复制或移动对象本身 (
Foo
( - 您不想要具有某种排除移动语义的空状态的包装器
- 对象本身(
Foo
(应该存储在堆上,使其生存期独立于控制流 - 对象本身(
Foo
(一旦不再使用就应该删除
由于构建/销毁,复制和移动是将对象移入/移出容器的唯一方法,唯一剩下的就是包装器对象,当移入/移出容器时会复制。
您可以自己创建此类对象,如下所示:
// LICENSE: MIT
#include <memory>
#include <utility>
template<typename T>
class shared_ref {
public:
template<typename ...Args>
shared_ref(Args&&... args)
: data{new T(std::forward<Args>(args)...)}
{}
shared_ref(shared_ref&&) = delete;
shared_ref& operator=(shared_ref&&) = delete;
T& get() noexcept {
return *data;
}
const T& get() const noexcept {
return *data;
}
operator T&() noexcept {
return get();
}
operator const T&() const noexcept {
return get();
}
void swap(shared_ref& other) noexcept {
return data.swap(other);
}
private:
std::shared_ptr<T> data;
};
template<class T>
void swap(shared_ref<T>& lhs, shared_ref<T>& rhs) noexcept {
return lhs.swap(rhs);
}
我把它留给读者练习,以添加对基类的Allocator
、Deleter
、operator[]
、隐式转换构造器的支持。
然后可以按如下方式使用:
#include <iostream>
int main() {
shared_ref<int> r; // default initialized
std::cout << "r=" << r << std::endl;
r = 5; // type conversion operator to reference
std::cout << "r=" << r << std::endl;
shared_ref<int> s{7}; // initialized with forwarded arguments
std::cout << "s=" << s << std::endl;
std::swap(r, s);
std::cout << "r=" << r << ", " << "s=" << s << std::endl;
s = r; // copy assignment operator
std::cout << "s=" << s << std::endl;
const shared_ref<int> t{s}; // copy constructor
std::cout << "t=" << t << std::endl;
//t = 8; // const ref from a const object is immutable
return 0;
}
相关文章:
- 何时在引用或唯一指针上使用移动语义
- C++优先级队列,按对象的唯一指针的特定方法升序排列
- 计算排序向量的向量中唯一值的计数
- 如何使用Visual Studio 2017在C++中为参数化对象数组使用唯一指针
- 通过组合不同的类型来创建唯一的id
- 使用Unique_ptr确保工厂中的对象唯一
- c++多进程编写一个唯一的文件
- 在以唯一ptr为值的C++映射中,动态内存何时会被销毁
- 如何更改唯一指针向量的可见性
- 在C++的两个字符串中连接以逗号分隔的唯一值
- 共享指针和具有自定义删除程序的唯一指针之间的语法差异背后的任何原因
- C++尝试深度复制唯一指针时出现内存访问冲突
- 具有引用成员的结构是否具有唯一的对象表示形式
- 使用 RTTI 克隆唯一指针的向量
- 如何在 c++ 中迭代数组中的唯一元素
- C++ 警告:将新创建的 gsl::owner<> 分配给非所有者
- 为什么我无法创建唯一指针
- 堆分配的对象是否存在永不为空的唯一所有者?
- 容器,其中每个项可以有多个非唯一键 (c++17)
- weak_ptr还是shared_ptr应该从唯一所有者集合返回