std :: move used,移动构造函数调用但对象仍然有效

Won*_*Boi 1 c++ move rvalue-reference

有人可以解释为什么通过std :: move传递给新对象的原始对象之后仍然有效吗?

#include <iostream>

class Class
{

public:
    explicit Class(const double& tt) : m_type(tt)
    {
        std::cout << "defaultish" << std::endl;
    };

    explicit Class(const Class& val) :
        m_type(val.m_type)
    {
        std::cout << "copy" << std::endl;
    };

    explicit Class(Class&& val) :
        m_type(val.m_type)
    {
        m_type = val.m_type;
        std::cout << "move: " << m_type << std::endl;
    };

    void print()
    {
        std::cout << "print: " << m_type << std::endl;
    }

    void set(const double& tt)
    {
        m_type = tt;
    }

private:

    double m_type;    
};

int main ()
{
    Class cc(3.2);

    Class c2(std::move(cc));

    c2.print();

    cc.set(4.0);
    cc.print();


    return 0;
}
Run Code Online (Sandbox Code Playgroud)

它输出以下内容:

defaultish
move: 3.2
print: 3.2
print: 4
Run Code Online (Sandbox Code Playgroud)

我希望对cc.set()和cc.print()的调用失败......

更新 由于下面的答案,我们已经确定1)我没有在移动构造函数中移动任何东西,2)std::move()在int或double上没有做任何事情,因为移动这些类型比简单复制更昂贵.下面的新代码将类的私有成员变量更新为std :: string而不是double,并在Class的移动构造函数中设置此私有成员变量时正确调用std :: move,从而产生一个输出,显示如何std :: move导致有效但未指定的状态

#include <iostream>
#include <string>

class Class
{

public:
    explicit Class(const std::string& tt) : m_type(tt)
    {
        std::cout << "defaultish" << std::endl;
    };

    explicit Class(const Class& val) :
        m_type(val.m_type)
    {
        std::cout << "copy" << std::endl;
    };

    explicit Class(Class&& val) : m_type(std::move(val.m_type))
    {
        std::cout << "move: " << m_type << std::endl;
    };

    void print()
    {
        std::cout << "print: " << m_type << std::endl;
    }

    void set(const std::string val )
    {
        m_type = val;   
    }

private:

    std::string m_type;    
};

int main ()
{
    Class cc("3.2");

    Class c2(std::move(cc));
    c2.print( );

    cc.print();
    cc.set( "4.0" );
    cc.print();

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

最后输出:

defaultish
move: 3.2
print: 3.2
print: 
print: 4.0
Run Code Online (Sandbox Code Playgroud)

Lig*_*ica 10

因为标准是这样说的.

已移动的对象具有有效但未指定的状态.这意味着你仍然可以使用它们,但是你无法确定它们将处于什么状态.它们看起来就像它们在移动之前所做的那样,取决于将数据"移出"它们的最有效方法是什么.例如,从一个"移动" int是没有意义的(你必须做额外的工作来重置原始值!)所以从一个"移动" int实际上只是一个副本.a也是如此double.

虽然在这种情况下,它更多地与你实际上没有移动任何事实有关.

  • 根据经验,您可以在没有前提条件(包括赋值和销毁)的移动对象上调用成员函数. (3认同)