以支持移动语义的std::list
为例。
std::list<std::string> X;
... //X is used in various ways
X=std::list<std::string>({"foo","bar","dead","beef"});
自 C++11 以来,编译器进行赋值的最直接方式是:
- 销毁
X
- 构造
std::list
- 将
std::list
移动到X
现在,不允许编译器执行以下操作:
- 摧毁X
- 就地构造
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"}.
在你的例子中,实际发生的事情是:
- build 一个临时的
- 在 X 上用临时调用移动赋值运算符
在大多数对象上,例如 std::list,与简单地构造一个对象相比,这实际上并不昂贵。
然而,它仍然会导致对第二个 std::list 的内部存储进行额外分配,这是可以避免的:如果可能的话,我们可以重用已经为 X 分配的内部存储。发生的事情是:
- 构造:临时为元素分配一些空间
- 移动:指针移动到X; X之前使用的空间被释放
有些对象会重载赋值运算符以获取初始化列表,std::vector 就是这种情况。和 std::list .这样的运营商可能会使用内部已经分配的存储,这是这里最有效的解决方案。
//请在这里插入关于过早优化的通常的杂乱无章
关于c++ - 减少临时对象到就地施工的分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41402924/