当引用一次时,编译器是否可以隐式std :: move参数?

Mik*_*ler 6 c++ compiler-construction move-semantics c++11

假设我有一个带有setter的简单类:

class MyClass
{
public:
    void setName(std::string name)
    {
        _name = std::move(name);
    }

private:
    std::string _name;
};
Run Code Online (Sandbox Code Playgroud)

我在std::move这里使用,但是如果我要省略这个并且只是写_name = name,那么编译器是否会隐式移动name参数,因为它不会在setter中的任何其他地方使用?它几乎可以被视为赋值表达式中的右值,因为它在其他任何地方都没有被名称引用.

编译器可以这样做吗?现有的编译器会这样做吗?

Cas*_*eri 5

添加在什么上面纳瓦兹。在假设规则下,如果编译器可以证明在移动和复制之间的不同行为是不可观察的,则允许进行移动。(我相信这对于编译器来说确实很难,除了琐碎的类型之外,对于它们来说根本没有克服应对的好处。)

我不知道是否有任何编译器正在执行此操作。(我猜不会!)

AFAIK,出于重载解析的目的,将左值视为右值的唯一情况是在return语句,throw表达式和异常声明(即objectin 的声明catch (type object))中。此外,必须满足一些条件(基本上与复制省略相同):

当满足或将要执行复制操作的省略标准时,除非源对象是函数参数,并且要复制的对象由左值指定,选择重载构造函数的重载分辨率为首先执行,就好像该对象是由右值指定的。[...]

最后,请注意,上述情况涉及构造。它们不像OP的问题那样涵盖任务。


Naw*_*waz 2

如果编译器能够证明这样做是安全的,那么它可能会这样做——这将是一种优化 。但这不是语言所要求的。因此,为了确保论点得到转移,你必须像你所做的那样明确地做到这一点——你在这方面无法改进。setName()

  • 编译器必须证明复制和移动构造函数执行相同的操作,否则就违反了 as-if 规则。如果它们相同,则移动就没有优化。 (2认同)
  • @Nawaz:是的,一个实现*可以*说它知道有关内存分配的所有信息,因为这都是实现的一部分。所以它可以省略副本。我想说的是,在整个实现中*不要*说他们了解内存分配的所有内容,因为他们希望它是动态链接和/或可挂钩的。顺便说一句,关于标准允许/保证的内容,我认为您的答案是正确的。 (2认同)