复制elision:当在return语句中使用三元表达式时,移动构造函数不被调用? [英] copy elision: move constructor not called when using ternary expression in return statement?

查看:158
本文介绍了复制elision:当在return语句中使用三元表达式时,移动构造函数不被调用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下示例:

#include <cstdio>

class object
{
public:
    object()
    {
        printf("constructor\n");
    }

    object(const object &)
    {
        printf("copy constructor\n");
    }

    object(object &&)
    {
        printf("move constructor\n");
    }
};

static object create_object()
{
    object a;
    object b;

    volatile int i = 1;

// With #if 0, object's copy constructor is called; otherwise, its move constructor.
#if 0
    if (i)
        return b; // moves because of the copy elision rules
    else
        return a; // moves because of the copy elision rules
#else
    // Seems equivalent to the above, but behaves differently.
    return i ? b : a; // copies (with g++ 4.7)
#endif
}

int main()
{
    auto data(create_object());

    return 0;
}

从C ++ 11工作草案中考虑这一点,n3337.pdf ,12.8 [class.copy],第32点:

And consider this bit from the C++11 Working Draft, n3337.pdf, 12.8 [class.copy], point 32:


当满足复制操作的标准时,事实上源对象是函数参数并且要被复制的对象由左值指定,重载分辨率选择用于副本的构造函数首先被执行,就好像对象由右值指定。如果重载分辨率失败,或者如果所选构造函数的第一个参数的类型不是对象类型的可值引用(可能是cv限定的),则会再次执行重载分辨率,将对象视为左值。 [注意:无论是否发生复制检测,都必须执行这种两级重载分辨率。如果没有执行elision,它确定要调用的构造函数,并且即使调用被省略,所选构造函数也必须可访问。 -end note]

When the criteria for elision of a copy operation are met or would be met save for the fact that the source object is a function parameter, and the object to be copied is designated by an lvalue, overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue. If overload resolution fails, or if the type of the first parameter of the selected constructor is not an rvalue reference to the object’s type (possibly cv-qualified), overload resolution is performed again, considering the object as an lvalue. [Note: This two-stage overload resolution must be performed regardless of whether copy elision will occur. It determines the constructor to be called if elision is not performed, and the selected constructor must be accessible even if the call is elided. —end note ]

因此,如果我们使用 #if 1 例如,移动构造函数首先在返回对象时尝试,然后是复制构造函数。因为我们有一个移动构造函数,它被用来代替复制构造函数。

Thus, if we use #if 1 in the example, the move constructor is first tried when returning the object, and then the copy constructor. Since we have a move constructor, it is used instead of the copy constructor.

在最后 return create_object()但是,我们观察到move构造函数不使用。是或这是不是违反语言规则?该语言是否需要在最后的 return 语句中使用move构造函数?

In the last return statement in create_object() however, we've observed that the move constructor is not used. Is or is this not a violation of the language rules? Does the language require that the move constructor is used in the last return statement?

推荐答案

条件运算符的规范如此复杂,可怕。但我相信你的编译器在它的行为是正确的。请参见5.16 [expr.cond] / p4:

The specification for the conditional operator is so complicated it is scary. But I believe that your compiler is correct in its behavior. See 5.16 [expr.cond]/p4:


如果第二个和第三个操作数是相同值的glvalues
类别,具有相同的类型,结果是该类型和值
category ...

If the second and third operands are glvalues of the same value category and have the same type, the result is of that type and value category ...

另见12.8 [class。复制],p31,b1,其描述允许复制允许的情况:

Also see 12.8 [class.copy], p31, b1 which describes when copy elision is allowed:


c>语句在一个类返回类型的函数中,当
表达式是一个非易失性自动对象(其他
不是一个函数或catch子句参数)的名称具有相同的cv-
不合格类型作为函数返回类型,复制/移动操作
可以省略...

in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object (other than a function or catch-clause parameter) with the same cv- unqualified type as the function return type, the copy/move operation can be omitted ...

表达式不是自动对象的名称,而是一个条件表达式(并且条件表达式是一个左值)。所以在这里不允许复制elision,并且没有什么其他说,lvalue表达式可以假装是重载解析的右值。

The expression is not the name of an automatic object, but is a conditional expression (and that conditional expression is an lvalue). So copy elision is not allowed here, and there is nothing else that says that the lvalue expression can pretend to be an rvalue for overload resolution.

这篇关于复制elision:当在return语句中使用三元表达式时,移动构造函数不被调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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