c++ - move 语义和参数评估顺序

标签 c++ c++11 move-semantics operator-precedence

考虑以下几点:

std::string make_what_string( const std::string &id );

struct basic_foo
{
    basic_foo( std::string message, std::string id );
};

struct foo
    : public basic_foo
{
    foo::foo( std::string id)
        : basic_foo( make_what_string( id ), std::move( id ) ) // Is this valid?
    {
    }
};

由于未指定 C++ 中的参数评估顺序,我想知道是否 这条线

basic_foo( make_what_string( id ), std::move( id ) )

上面的代码是有效的。

我知道 std::move 只不过是一个 Actor ,但什么时候是 std::string move ctor 被执行?在评估了所有参数之后,是时候调用了 基础构造函数?或者这是在评估参数期间完成的?在 换句话说:

编译器会这样做吗:

std::string &&tmp2 = std::move(id);
std::string tmp1 = make_what_string(id);
basic_foo(tmp1, tmp2);

这是有效的。或者这样:

std::string tmp2 = std::move(id);
std::string tmp1 = make_what_string(id);
basic_foo(tmp1, tmp2);

这是无效的。请注意,在这两种情况下,订单都是“意外的” 一个。

最佳答案

参见第 1.9 节:

Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced.

When calling a function (whether or not the function is inline), every value computation and side effect associated with any argument expression, or with the postfix expression designating the called function, is sequenced before execution of every expression or statement in the body of the called function. [ Note: Value computations and side effects associated with different argument expressions are unsequenced. —end note ]

我认为问题在于,参数的初始化是否被认为是与参数表达式相关的副作用并不是很清楚。但是,它似乎得到了第 5.2.2 节的支持:

The initialization and destruction of each parameter occurs within the context of the calling function.

在同一段中还有一个注释,使它更清楚一点:

When a function is called, each parameter (8.3.5) shall be initialized (8.5, 12.8, 12.1) with its corresponding argument. [ Note: Such initializations are indeterminately sequenced with respect to each other (1.9) — end note ]

所以是的,参数的初始化相对于彼此是不确定的。初始化可能按以下任一顺序进行:

std::string message = make_what_string(id);
std::string id = std::move( id );

std::string id = std::move( id );
std::string message = make_what_string(id);

在第二种情况下,make_what_string 最终处理的是一个 move 的字符串。

所以,即使 std::move 实际上并没有 move 任何东西,重要的是实际的 moving 相对于另一个参数也是无序的。

basic_string(basic_string&& str)的move构造函数的定义说明:

[...] str is left in a valid state with an unspecified value.

所以你没有未定义的行为,你有未指定的行为。

关于c++ - move 语义和参数评估顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15680489/

相关文章:

c++ - 重置 move 对象的常用惯用法是什么?

c++ - 在 C++11 中抛出异常时是否使用 move 语义?

c++ - 使用 MFC 中的异步过程调用中断接受 winsock 调用

c++ - C++标准库和POSIX等系统接口(interface)标准有什么关系?

c++: std::bind() 'know' 模板参数是指静态函数还是成员函数?

c++ - 将函数参数限制为某些枚举值

c++ - ref-qualifier `const &&` 有什么用?

c++ - 在 C++ 中线程化以保持两个函数并行运行

c++ - "this"指针上的指针运算

C++ 11 : is a defaulted copy constructor user declared?