有没有办法将分配的对象实际移动到 std::list
Is there way to actually move allocated object to 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 data
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>>
并使用它。
在 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 data
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>>
并使用它。