移动语义和函数顺序评估 [英] Move semantics and function order evaluation

查看:110
本文介绍了移动语义和函数顺序评估的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有以下:

#include <memory>
struct A { int x; };

class B {
  B(int x, std::unique_ptr<A> a);
};

class C : public B {
  C(std::unique_ptr<A> a) : B(a->x, std::move(a)) {}
};



如果我正确理解关于未指定的函数参数顺序的C ++规则,这个代码是不安全的。如果 B 的构造函数的第二个参数首先使用move构造函数构造,则 a 现在包含 nullptr 并且表达式 a-> x 将触发未定义的行为(可能segfault)。

If I understand the C++ rules about "unspecified order of function parameters" correctly, this code is unsafe. If the second argument to B's constructor is constructed first using the move constructor, then a now contains a nullptr and the expression a->x will trigger undefined behavior (likely segfault). If the first argument is constructed first, then everything will work as intended.

如果这是一个正常的函数调用,我们可以创建一个临时的:

If this were a normal function call, we could just create a temporary:

auto x = a->x
B b{x, std::move(a)};

但在类初始化列表中,我们没有创建临时变量的自由。

But in the class initialization list we don't have the freedom to create temporary variables.

假设我不能改变 B ,有没有可能的方法来完成上述?即在同一个函数调用表达式中取消引用并移动 unique_ptr 而不创建临时变量?

Suppose I cannot change B, is there any possible way to accomplish the above? Namely dereferencing and moving a unique_ptr in the same function call expression without creating a temporary?

B 的构造函数,但不添加新方法,例如 setX(int)

What if you could change B's constructor but not add new methods such as setX(int)? Would that help?

谢谢

推荐答案

构造 B

C(std::unique_ptr<A> a) : B{a->x, std::move(a)} {}
//                         ^                  ^ - braces


b $ b

§8.5.4/ 4 [dcl.init.list]


braced-init-list initializer-list ,包括包扩展的任何结果(14.5.3) ,按出现的顺序进行评估。也就是说,与给定的< em>初始化子句相关联的每个值计算和副作用在与其之后的任何< em>初始化子句相关联的每个值计算和副作用之前被排序

Within the initializer-list of a braced-init-list, the initializer-clauses, including any that result from pack expansions (14.5.3), are evaluated in the order in which they appear. That is, every value computation and side effect associated with a given initializer-clause is sequenced before every value computation and side effect associated with any initializer-clause that follows it in the comma-separated list of the initializer-list.

这篇关于移动语义和函数顺序评估的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆