unique-ptr 相关问题

std :: unique_ptr是一个智能指针,通过指针保留对象的唯一所有权。 unique_ptr不可复制或可复制,unique_ptr的两个实例无法管理同一对象。

无法使用带有多个隐式转换步骤的复制初始化[重复]

我无法理解为什么以下复制初始化无法编译: #包括 结构体基{}; 结构派生:base{}; 结构测试 { 测试(std::unique_ptr<...

回答 3 投票 0

如何获取unique_ptr中存储的数组大小?

如果我这样做: std::unique_ptr uparr(new int[1984]); 我将 uparr 传递给某人,但没有将 1984 传递给他们,他们可以看到它有多少个元素吗? 又名是否有相当于向量的.

回答 5 投票 0

多态对象和unique_ptr的向量

我正在尝试做一项作业,并决定这次正确管理内存,但最终问题多于答案。我想要一个父类的子向量,例如 vect...

回答 1 投票 0

尝试将 std::make_unique 声明为我的模板类的友元时出现 MSVC 错误

显然今天,MSVC 正在尽力说服我改用 clang。但我不会放弃。早些时候,我问了这个问题,想知道如何声明 std::make_unique 作为我班级的朋友。 我...

回答 2 投票 0

如何填充指向 char 数组的 unique_ptr?

可以将一些内容放入指向 char 数组的 unique_ptr 中,如下所示: #包括 #包括 #定义 LEN 100 使用 std::cout、std::cin...

回答 1 投票 0

将 unique_ptr 传递给派生类会导致 SEGFAULT

有人可以向我解释为什么在这里执行函数 foo() 会导致 SEGFAULT 吗?当我将 D 类中的 unique_ptr 对象更改为包含 B 类对象而不是 A 时,一切正常。 A级 { ...

回答 1 投票 0

有没有办法在不同范围内共享shared_ptr的一部分?

因此,如果您想共享shared_ptr过去元素x中的所有内容,您可以编写如下内容: int main(){ std::shared_ptr _vals = std::make_unique 因此,如果您想在 shared_ptr 过去的元素 x 中共享所有内容,您可以编写如下内容: int main(){ std::shared_ptr<float[]> _vals = std::make_unique<float[]>(70); for(uint32_t i = 0; i < 10; ++i) _vals[i] = i; //range from 2 - end of _vals // x = 2 in this case std::shared_ptr<float[]> _partial(_vals, &_vals[2]); for(uint32_t i = 0; i < 5; ++i) std::cout<<_partial[i]<<" "; std::cout<<std::endl; return 0; } 所以输出将是: 2 3 4 5 6 因此 _partial 将从 _vals.get() + 2 指向 _vals 的末尾。但是,如果我想让它指向 (2-5), (70-end) 例如,我想知道是否可以将地址分配给 _partial 来完成此操作? 例如,如果这有效: int main(){ std::shared_ptr<float[]> _vals = std::make_unique<float[]>(70); for(uint32_t i = 0; i < 70; ++i) _vals[i] = i; //range from 2 - 5, and then range from 70-73 std::shared_ptr<float[]> _partial(_vals, &_vals[2]); float** begin = &(&_vals[70]); float** end = &(&_vals[73]); float** beg_2 = &(&_partial[2]); for(;begin != end; ++(*begin), ++(*beg_2)){ beg_2 = begin; } //so technically _partial[0] would point to _vals[2] but _partial[3] would point to _vals[70] for(uint32_t i = 0; i < 5; ++i) std::cout<<_partial[i]<<" "; std::cout<<std::endl; return 0; } 但是,如果我尝试编译它,我会收到错误: cannot take the address of an rvalue of type 'float *' float** begin = &(&_vals[70]); 有办法完成我想做的事情吗? A shared_ptr 是这项工作的错误工具。 A shared_ptr 拥有某个对象并指向某个(可能不同的)对象。它没有实现足够的逻辑来执行像您想要的0 -> 0, 1 -> 1, 2 -> 2, 3 -> 70这样的映射。 (它也不应该实现这个逻辑。这不是一个简单的任务。) 实现您自己的类来实现此行为。这应该可以帮助您开始: template<typename T> class subsequence { public: struct interval { std::size_t begin, length; }; private: std::shared_ptr<T[]> storage; std::vector<interval> pieces; public: subsequence(std::shared_ptr<T[]> storage, std::initializer_list<interval> pieces) : storage(std::move(storage)), pieces(pieces) { } T &operator[](std::size_t i) { for(interval const &piece : pieces) { if(i < piece.length) return storage[piece.begin + i]; else i -= piece.length; } } }; int main() { std::size_t const size = 80; std::shared_ptr<float[]> vals = std::make_unique<float[]>(size); for(uint32_t i = 0; i < size; ++i) _vals[i] = i; subsequence partial(vals, {{2, 3}, {70, 3}}); // range from 2 - 5, and then range from 70-73 for(uint32_t i = 0; i < 6; ++i) std::cout << partial[i] << " "; std::cout << "\n"; } 智能指针都是关于所有权的——谁拥有你分配的那块内存?你不能让一个智能指针拥有整个数组,而另一个智能指针只拥有其中的一部分,这在物理上是不可能的。 如果分散范围需要是原始数组的共享指针,您可以捕获共享指针对中的信息,然后将它们放入这些对的向量中。 我冒昧地将原始数组设为 99 个元素,因此第二个跨度是有效的。 #include <iostream> #include <memory> #include <utility> #include <vector> using std::cout; using std::exchange; using std::ostream; using std::pair; using std::shared_ptr; using std::vector; namespace { using shared_float_span = pair<shared_ptr<float>, shared_ptr<float>>; using vector_span = vector<shared_float_span>; auto operator<<(ostream& out, shared_float_span const& s) -> ostream& { auto sep = ""; auto it = s.first.get(); auto end = s.second.get(); while (it != end) { out << exchange(sep, " ") << *it; ++it; } return out; } auto operator<<(ostream& out, vector_span const& v) -> ostream& { auto sep = ""; for (auto&& x : v) { out << exchange(sep, " ") << x; } return out; } } // anon int main(){ shared_ptr<float[]> vals = std::make_unique<float[]>(99); for(uint32_t i = 0; i < 99; ++i) { vals[i] = 1000 + i; } shared_float_span a{ shared_ptr<float>(vals, &vals[2]), shared_ptr<float>(vals, &vals[6]) }; shared_float_span b{ shared_ptr<float>(vals, &vals[70]), shared_ptr<float>(vals, &vals[74]) }; vector_span v{a, b}; cout << v << "\n"; } 因此 _partial 将从 _vals.get() + 2 指向 _vals 的末尾。 不。指针指向单个对象,而不是范围。在您的情况下,_partial指向_vals.get() + 2。只是一个元素。允许访问 _vals 的某个子范围的想法是基于您采用的如何访问元素的约定。举个例子:您的循环打印了 _vals 的第三个到第七个元素。您的文本表明循环应该“到 _vals 的末尾”(第 70 个元素),但事实并非如此。为什么?因为你的循环在索引 5 而不是 68 处结束。这不是 _partial 固有的东西,而是你如何使用 _partial 的结果。同样,循环从索引 0(_partial)开始。这是你的选择。虽然从索引 0 开始是常规的,但这只是常规的。在您的特定情况下, _partial 指向数组的第三个元素。这意味着表达式 _partial.get()[-2] 是合法的,并且指向数组的第一个元素。 (表达式 _partial[-2] 在实践中可能也有效,但 cppreference.com 表示该行为未定义。)您的起点,就像您的终点一样,不是 _partial 固有的东西,而是您如何使用 _partial 的结果.结果是,您想要的行为不是关于所有权,而是关于如何使用您拥有的数据。 重新提出问题 因此我们可以从您的问题中消除共享所有权。您有一个数组,并且需要一种方法来迭代该数组的子范围。数组如何拥有并不重要;该问题只需要存在一个数组和一种指定子范围的方法。 简单的情况是子范围是连续的。在这种情况下,可以通过其开始和结束来指定子范围。执行此操作的常见方法是提供指向开头的指针 (_partial) 和大小(如果我们按照循环进行,则提供 5;如果我们使用“68 的结尾”,则提供 _vals) 。你知道怎么做。您的问题是如何指定不连续的子范围。非连续范围面临的问题是 std::shared_ptr::operator[] 和内置 [] 运算符是为连续范围设计的。对象 _partial[2] 和 _partial[3] 必须位于相邻的内存位置。这就是这个运算符的工作原理。答案 那么可以做什么呢?在 C++17 中,您可以编写适配器类。这样的类可以包装一个数组并提供一个 operator[] 来完成您想要的操作。也就是说,它将有一个用于数组访问的数据成员(例如您的std::shared_ptr<float[]>),并且它会以某种方式存储您想要访问的索引。我会将详细信息留给读者(或其他答案),因为这个答案花了很长时间才达到这一点。虽然这个问题被标记为 C++17,但我会注意到在 C++20 中,有范围。特别是,filter view可用于选择您想要的基础视图的哪些元素。例如,您可以为过滤器视图提供一个谓词,当参数减去 true 的地址在 2 到 5 之间或 60 到 65 之间时,该谓词会通过(返回 _vals)。我会将详细信息留给读者,因为该问题要求 20 岁之前的答案。

回答 4 投票 0

unique_ptr自定义删除器的不同场景

正在阅读Nicholai Jossutis,STL 书。有一个部分像 d d; // 删除器类型的实例 unique_ptr p4(new int, D()); ...

回答 1 投票 0

处理 std::map 内的 unique_ptr<pure_virtual_class> 向量时出现意外编译错误

#包括 #包括 #包括 #包括 基类{ 民众: 虚拟 ~Base() = 默认值; 虚拟无效 doIt() = 0; 民众: int 基数 =...

回答 1 投票 0

使用 unique_prt:free() 方法重置:无效指针

当我使用 reset 重新绑定 unique_ptr 时,发生了一些不好的事情,但是当使用 std::make_unique 时,一切正常 诠释主要(){ unique_ptr p= nullptr; 自动 l=[&p]()->void{ ...

回答 1 投票 0

使用包含在 std::unique_ptr 中的对象进行多态数据类型转换

我有一个类层次结构如下 #包括 #包括 A类 { 民众: 虚拟无效打印()= 0; }; B类:公共A { 民众: 无效打印() { ...

回答 2 投票 0

为什么自 C++17 以来,由 new 初始化的 std::unique_ptr 没有内存泄漏? [重复]

让我引用 Professional C++ 5th 中的部分内容。编辑(第 237 页): 在 C++17 之前,您必须使用 make_unique() ... 考虑以下对名为 foo() 的函数的调用: foo(unique_ptr 让我引用Professional C++ 5th 中的部分内容。 ed.(第 237 页): 在 C++17 之前,您必须使用 make_unique() ... 考虑以下对名为 foo() 的函数的调用: foo(unique_ptr<Simple> { new Simple{} }, unique_ptr<Bar> { new Bar { data() } }); 如果Simple或Bar的构造函数,或data() 函数,抛出异常,具体取决于您的编译器 优化,有可能是 Simple 或 Bar 对象 会被泄露。使用make_unique(),什么都不会泄漏: foo(make_unique<Simple>(), make_unique<Bar>(data())) 自 C++17 起,两者 调用 foo() 是安全的,但我仍然建议使用 make_unique() 作为 它导致代码更容易阅读。 我知道为什么在 C++17 之前它不安全,因为 new 可能首先发生并且 data() 可能会在 new 的结果传递给 unique_ptr 之前被调用,所以当异常抛出时,内存泄漏发生。但为什么它从 C++17 开始就变得安全了?

回答 0 投票 0

如何将变量传递给 std::unique_ptr 的自定义删除器(lambda 函数)?

我想打开一个文件并对文件执行一些操作,testOpen 和 testClose 是 API 函数 test_open 和 test_close 的包装器,因此如果执行这些操作时出错

回答 1 投票 0

unique_ptr C++的无序映射

类项目{ ... }; 类容器{ 民众: void AddItem(项目*项目){ 如果 (items.find(item) == items.end()) { 项目[项目] = make_unique(项目); } } std::无序...

回答 1 投票 0

Klocwork 对 make_unique 提出警告

我有以下结构, 结构我的结构{ 布尔我布尔, 诠释我的诠释, std::unique_ptr> myUniquePtr; } ; 假设我构建了以下对象, MyStr...

回答 0 投票 0

std::unique_ptr with custom deleter: regular vs array type

说我有两个功能: const char* get_string(int id); bool free_string(const char* str); 我想为他们写一个 std::unique_ptr 包装器。 根据这个答案,我创建了以下内容: 模板 ...

回答 1 投票 0

无法使用 lambda 作为自定义删除器构造 std::unique_ptr

我正在尝试使用自定义删除器声明 std::unique_ptr: 使用 FILE = int; 文件 *f = nullptr; std::unique_ptr pf(f, [](FILE *f) {}); 但没有成功。怎么了? 如何使用 lambd...

回答 1 投票 0

使用三元运算符创建静态 unique_ptr

我有一个名为 IDBAbstractFactory 的接口和两个派生类 CPostgreSQLDBAbstractFactory 和 COracleDBAbstractFactory。 我正在尝试创建一个 std::unique_ptr 与...

回答 3 投票 0

std::move() 会调用 LHS unique_ptr 所属对象的析构函数吗?

考虑以下代码: #包括 #包括 #包括 // 我知道这是 violationg 规则 5 类 ElfData { 私人的: std::字符串名称; 普...

回答 1 投票 0

我需要在 `std::unique_ptr` 删除器中使用 `__stdcall` 吗?

我想通过 std::unique_ptr 管理一个 WinAPI 函数对: #包括 int* __stdcall construct(){ 返回新的 int{5}; } void __stdcall destruct(int* v){ 删除 v; } 诠释主要(){ ...

回答 1 投票 0

© www.soinside.com 2019 - 2024. All rights reserved.