有没有办法将分配的对象实际移动到 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_frontemplace_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::extractstd::map::insert 的关联容器最近有一些例外。理论上,std::list 将来也可能得到它们。

真链表

没有什么能阻止您创建 std::list<std::unique_ptr<T>> 并使用它。