gpt4 book ai didi

c++ - 利用容器的移动语义和元素初始化

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:08:29 25 4
gpt4 key购买 nike

经常看到使用 STL 算法的示例用列表初始化容器来说明,例如:

std::vector< int > v{1, 2, 3, 4};

但是当这种方法用于(重量级)(不像ints)时,它意味着过度的复制操作,即使它们被传递给右值(移至),因为上面示例中使用的std::initializer_list 仅提供const_iterator

为了解决这个问题,我使用了以下 (C++17) 方法:

template< typename Container, typename ...Args >
Container make_container(Args &&... args)
{
Container c;
(c.push_back(std::forward< Args >(args)), ...);
// ((c.insert(std::cend(c), std::forward< Args >(args)), void(0)), ...); // more generic approach
return c;
}

auto u = make_container< std::vector< A > >(A{}, A{}, A{});

但是当我执行以下操作时,它变得不令人满意:

A a;
B b;
using P = std::pair< A, B >;
auto v = make_container< std::vector< P > >(P{a, b}, P{std::move(a), std::move(b)});

在这里,我想通过移动操作替换复制操作来为每个值保存一个复制操作(假设移动 AB 更便宜然后复制),但通常不能,因为函数参数的求值顺序在 C++ 中未定义。我目前的解决方案是:

template< Container >
struct make_container
{

template< typename ...Args >
make_container(Args &&... args)
{
(c.push_back(std::forward< Args >(args)), ...);
}

operator Container () && { return std::move(c); }

private :

Container c;

};

A a; B b;
using P = std::pair< A, B >;
using V = std::vector< P >;
V w = make_container< V >{P{a, b}, P{std::move(a), std::move(b)}};

在构造函数体中做一些重要的工作通常被认为是一种不好的做法,但在这里我集中使用了 list-initialization 的特性——事实上它被严格保留- 向右排序。

从某些特定的角度来看,这是完全错误的方法吗?除了上述方法之外,这种方法还有哪些缺点?当前(在 C++11、C++14、C++1z 中)是否有另一种技术可以实现可预测的函数参数求值顺序?

最佳答案

有一个更好的解决方案:

template<class Container, std::size_t N>
inline Container make_container(typename Container::value_type (&&a)[N])
{
return Container(std::make_move_iterator(std::begin(a)), std::make_move_iterator(std::end(a)));
}

你可以这样使用它:

make_container<std::vector<A>>({A(1), A(2)})

它不需要可变参数模板,它仍然是列表初始化但不是 std::initializer_list,这次它是一个普通数组,因此您可以从中移动元素。

与您的原始解决方案相比的显着优势:

  • 更好的性能:它直接调用Container的ctor可以提供更好的性能(例如std::vector可以保留所有需要的内存)
  • Eval顺序保证:它是列表初始化

DEMO

关于c++ - 利用容器的移动语义和元素初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36077772/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com