c++ - 有没有办法将分配的对象实际移动到 std::list
问题描述
在 C 风格的链表中,您只需设置指向已分配对象的指针,而在 C++ 中,复制似乎是不可避免的。
天真的测试代码:
#include <cstring>
#include <iostream>
#include <chrono>
#include <memory>
#include <list>
#include <vector>
using std::cout;
struct LinkedS{
LinkedS *next = nullptr;
float f;
std::vector<float> v{1};
};
struct S{
float f;
std::vector<float> v{1};
};
int main()
{
S* s = new S;
cout << &s->v.front() << ' ' << &s->f << '\n';
std::list<S> li;
li.push_front( std::move( *s ) );
cout << &li.front().v.front() << ' ' << &li.front().f << '\n';
}
https://godbolt.org/z/33T4179Gj
这里vector内容实际上是移动的,但不幸的是struct数据还是被复制了。
解决方案
的这种用法new
不是一个好的 C++,它不是 Java/C#,new
除非你必须,否则不要使用,当你必须时,使用std::unique_ptr
.
你在找emplace_front
,emplace_back
?他们可以在其最终目的地构造存储的对象。
C++20
#include <list>
#include <vector>
struct S{
float f;
std::vector<float> v;
};
int main()
{
std::list<S> li;
li.emplace_front(42.4f,std::vector{1.f,2.f,3.f,4.f,5.f});
}
C++17
遗憾的是,在 C++20 之前,需要一个构造函数,聚合不计算在内。
#include <list>
#include <vector>
struct S{
float f;
std::vector<float> v;
S(float f, std::vector<float> v):f(f),v(std::move(v)){}
};
int main()
{
std::list<S> li;
li.emplace_front(42.4f,std::vector{1.f,2.f,3.f,4.f,5.f});
}
如果您确实需要将预分配的指针传递给容器,那是不可能的。本身std::list
不是链表,它仅对可能导致链表实现的操作有要求。此外,所有 STL 容器都使用可定制的分配器,并且每个分配器都拥有并为其容器提供存储,它不能从外部源传入。
尽管最近出现了一些带有节点std::map::extract
并std::map::insert
在节点上运行的关联容器的例外情况。理论上,std::list
将来可能也会得到它们。
真正的链表
没有什么能阻止你创造std::list<std::unique_ptr<T>>
和使用它。
推荐阅读
- typescript - 使用 dhtmlx 表单和 struts 2 上传文件
- python - Django 404:“找不到与查询匹配的对象实例”
- c# - 如何在 .Net Core 3 Worker 服务中设置应用程序设置
- javascript - 如何将读取为二进制字符串的文件转换为 Uint8Array,其值与使用 ArrayBuffer 时的值不同?
- javascript - 谷歌地图中的新错误
- swift - ios13 tls证书问题-连接错误
- android - 如何将位图传递给 android Worker?
- java - 在我解析 FileReader 期间,文件位置 0 出现意外的令牌结尾错误
- swift - 如何扩展 String 的 UnsafePointer
初始化器接受 NULL 指针? - r - R在切片向量时附加'NA'