c++ - 减少临时对象到就地施工的分配

标签 c++ optimization assignment-operator placement-new

以支持移动语义的std::list为例。

std::list<std::string> X;
... //X is used in various ways
X=std::list<std::string>({"foo","bar","dead","beef"});

自 C++11 以来,编译器进行赋值的最直接方式是:

  1. 销毁X
  2. 构造std::list
  3. std::list 移动到 X

现在,不允许编译器执行以下操作:

  1. 摧毁X
  2. 就地构造std::list

因为虽然这显然节省了另一个 memcpy,但它消除了赋值。使第二种行为成为可能和可用的便捷方法是什么?是否计划在未来的 C++ 版本中使用?

我的猜测是 C++ 仍然不提供,除了写作:

X.~X();
new(&X) std::list<std::string>({"foo","bar","dead","beef"});

我说得对吗?

最佳答案

您实际上可以通过定义 operator= 来获取初始化列表来实现。 对于 std::list,只需调用

    X = {"foo","bar","dead","beef"}.

在你的例子中,实际发生的事情是:

  1. build 一个临时的
  2. 在 X 上用临时调用移动赋值运算符

在大多数对象上,例如 std::list,与简单地构造一个对象相比,这实际上并不昂贵。

然而,它仍然会导致对第二个 std::list 的内部存储进行额外分配,这是可以避免的:如果可能的话,我们可以重用已经为 X 分配的内部存储。发生的事情是:

  1. 构造:临时为元素分配一些空间
  2. 移动:指针移动到X; X之前使用的空间被释放

有些对象会重载赋值运算符以获取初始化列表,std::vector 就是这种情况。和 std::list .这样的运营商可能会使用内部已经分配的存储,这是这里最有效的解决方案。

//请在这里插入关于过早优化的通常的杂乱无章

关于c++ - 减少临时对象到就地施工的分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41402924/

相关文章:

c++ - 在 C++ 中将 map (value,index) 转换为 vector (index,value) 的最快方法是什么?

c++ - 返回错误值的 bool 递归函数

c++ - 类定义中构造函数的模板特化

c++ - 在赋值运算符之前调用结构的析构函数

c++ - 绕过自动生成的赋值运算符(VS bug?)

C++ 无法使用 g++-mp-4.4 捕获从 Mac OS 中的 curlpp 抛出的异常

linux - Linux 上的 CPU 限制后台进程

language-agnostic - 如何减少本例中的代码重复

c - 避免使用货币进行浮点运算

c++ - "screwing up"赋值运算符会产生什么后果?