【问题标题】:Move constructor and non-const copy constructor移动构造函数和非常量复制构造函数
【发布时间】:2023-03-20 00:10:01
【问题描述】:

我是移动构造函数的新手,我从一些网站进行了调查并尝试使用 Visual Studio 11 Express Beta..

下面是我的测试代码...

#include <iostream>

using namespace std;

class Foo
{
public:
    Foo()
      : Memory(nullptr)
    {
        cout<<"Foo Constructor"<<endl;
    }
    ~Foo()
    {
        cout<<"~Foo Destructor"<<endl;
        if(Memory != nullptr)
            delete []Memory;
    }
    Foo(Foo& rhs)
      : Memory(nullptr)
    {
        cout<<"Copy Constructor"<<endl;

        //allocate
        //this->Memory = new ....
        //copy 
        //memcpy(this->Memory, rhs.Memory...);
    }

    Foo& operator=(Foo& rhs)
    {
        cout<<"="<<endl;
    }
    void* Memory;

    Foo(int nBytes) { Memory = new char[nBytes]; }

    Foo(Foo&& rhs)
    {
        cout<<"Foo Move Constructor"<<endl;
        Memory = rhs.Memory;
        rhs.Memory = nullptr;
    }
};

Foo Get()
{
    Foo f;
    return f; 
    //return Foo();
}
void Set(Foo rhs)
{
    Foo obj(rhs);
}
int main()
{
    Set(Get());
    return 0;
}

我不知道为什么它不会进入移动构造函数。

它实际上是来自 Get() 的右值;

如果我从 const 构造函数修改了非 const 复制构造函数,

它将进入移动构造函数。行为改变了...

谁能解释一下为什么会这样?

【问题讨论】:

  • delete [] void_ptr; 是未定义的行为。请注意,delete nullptr 非常好,无需事先检查。此外,不需要所有无用的样板代码。剪掉它,并将一个干净的例子粘贴到问题中。阅读sscce.org
  • 哦,问题的答案是:您很可能是outsmarted by the compiler(注意g 中缺少的构造副本,这是您的示例实际打印的内容)。启用优化后,编译器会简单地忽略所有这些移动/复制。
  • @Xeo:您​​的示例在X f() 中缺少return
  • @Mankarse:嗯……是的,谢谢。现在不行了重点仍然存在(这只是一个“错字”)。
  • 我看不到任何代码。请在您的问题正文中发布一个包含任何示例代码的完整问题。

标签: c++ visual-c++ c++11 visual-c++-2012


【解决方案1】:
#include <iostream>

using namespace std;

class Foo
{
public:
    Foo():
        Memory(nullptr)
    {
        cout<< this << "Foo Constructor"<<endl;
    }

    ~Foo()
    {
        cout<< this << "~Foo Destructor"<<endl;
        if(Memory != nullptr)
            delete []Memory;
    }

    Foo(Foo& rhs)
        :Memory(nullptr)
    {
        cout<<this << "Copy Constructor"<<endl;

        //allocate
        //this->Memory = new ....
        //copy 
        //memcpy(this->Memory, rhs.Memory...);
    }

    Foo& operator=(Foo& rhs)
    {
        cout<<"="<<endl;
    }
    void* Memory;

    Foo(int nBytes) { Memory = new char[nBytes]; }

    Foo(Foo&& rhs)
        {
        cout<<this << "Foo Move Constructor"<<endl;

                 Memory = rhs.Memory;


                 rhs.Memory = nullptr;
        }

};

Foo Get()
{
    Foo f;
    cout << &f << "f" <<endl;
    return f; 
}

void Set(Foo rhs)
{
    Foo obj(rhs);
    cout << &obj << "obj"<<endl;
}

int main()
{
    Set(Get());
    return 0;
}

输出...

0x7fffe38fa0a0 Foo Constructor
0x7fffe38fa0a0 f
0x7fffe38fa070 Copy Constructor
0x7fffe38fa070 obj
0x7fffe38fa070 ~Foo Destructor
0x7fffe38fa0a0 ~Foo Destructor

答案:由于命名返回值优化,参数 rhs 被就地构造为局部变量 f 的别名。 (也就是说rhs和f是同一个实例)。

由于rhs是一个左值,复制构造函数用于从rhs复制构造obj。

【讨论】:

    猜你喜欢
    • 2017-06-11
    • 1970-01-01
    • 2018-09-23
    • 2013-10-13
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多