【问题标题】:Confused when move constructor is called?调用移动构造函数时感到困惑?
【发布时间】:2014-08-24 00:32:59
【问题描述】:

我一直在为这个问题苦苦挣扎,但我找不到对此的解释。 假设我有以下代码

class foo
{
public:
    foo()
    {std::cout << "Regular constructor \n";}

    foo( const foo& a)                            //In abscence of const keyword the copy constructor is called
    {std::cout << "Copy constructor \n";}

    foo& operator=(const foo& a) 
    {std::cout << "Copy Assignment operator \n";}

    foo(foo&& a)
    {
        std::cout << "Move constructor \n";
    }

    foo& operator=(foo&& a) 
    {std::cout << "Move Assignment operator \n";}

    int a;
};


foo myfunction()
{
    foo d;
    d.a =120;
    return d;
}

现在如果我做这样的事情

foo a = myfunction();

这是我所期望的。 myfunction() 返回一个对象左值,但是由于 myfunction() 是临时的,它会返回一个右值。我对么 ?现在在这种情况下,将调用移动构造函数,这是有道理的。但是,如果我从复制构造函数中删除 const 关键字,则会调用复制构造函数而不是移动构造函数。谁能向我解释为什么会这样?提前致谢。

【问题讨论】:

  • 如果你通过在你的operator=() 实现中包含return *this; 来摆脱未定义的行为,那么我会得到我所期望的,这是对无参数构造函数的一次调用。因为复制错误。
  • 展示一个完整的可编译示例,并说明您使用的编译器和选项。
  • myfunction 被公然声明为返回纯右值,而不是左值。
  • 听说VS2012在某些情况下在Debug模式下不做复制省略
  • 有人可以帮忙吗,我在我的机器上使用 GCC 编译器和 c++14 版本并试图调用foo a = myfunction(); 但我无法在move constructor/move assignment operator 中接听电话。我在论坛里搜了一下,只能找到这个问题的讨论。

标签: c++ c++11 move-constructor


【解决方案1】:

VS2012 有一个讨厌的扩展,它允许临时对象绑定到左值引用。我们无法使用符合标准的现代编译器进行复制,实际上省略对复制/移动构造函数的调用(因为RVO)。应用选项fno-elide-constructors 表明即使没有const,它们确实调用了移动构造函数。

【讨论】:

【解决方案2】:

来自cppreference

每当一个对象从相同类型的xvalue初始化时,都会调用move构造函数,包括:

  • 初始化,T a = std::move(b);或 T a(std::move(b));,其中 b 的类型为 T

  • 函数参数传递:f(std::move(a));,其中 a 是 T 类型,f 是 void f(T t)

  • 函数返回:返回一个;在诸如 T f() 之类的函数中,其中 a 是具有移动构造函数的 T 类型。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多