移动语义机制

问题描述 投票:0回答:1

我已经开始学习C ++,但对移动语义有些疑问。当这本书说A的move构造函数“窃取”右值B的属性时,是否意味着指向值V的指针从B切换到A?因此,通过这种方式,A不需要分配内存的另一部分?

如果是这样,为什么在此代码中

class CBuffer{
private:
    int size;
    int csize;
    char* ptr;
    char rtp;
public:
    CBuffer(int size): size(size), csize(0){
        ptr = new char[size];
        *ptr = 'a';
    }

    CBuffer(const CBuffer& source): size(3), csize(source.csize) {
        this->ptr = new char[size];
        memcpy(this->ptr, source.ptr, size);
    }

    CBuffer(CBuffer&& source){
        this->ptr = source.ptr;
        this->size = source.size;
        std::cout << &this->ptr << std::endl;
        std::cout << &source.ptr << std::endl;
        source.ptr = nullptr;
    }

};



int main(){
    CBuffer a = CBuffer(1);
    CBuffer b = std::move(a);
    CBuffer c = b;

std::cout << &this->ptr << std::endl;
std::cout << &source.ptr << std::endl;

打印不同的地址?

c++ move-semantics
1个回答
0
投票

移动语义意味着我们无需创建另一个对象的副本,而是允许该对象获取此另一个对象内部的任何动态分配的内存。

我们通过在两者之间交换任何动态分配的内存来做到这一点,这意味着value(意味着存储在指针中的内存地址)现在,第一个对象中的指针将是新对象中指针的[value,并且我们在rvalue引用中放置了nullptr,因此当销毁它时,它也会销毁它。

我在代码中添加了一些内容:

  1. 我已经初始化了初始化列表中的所有变量。另外,我还删除了copy-ctor中大小的硬编码初始化。
  2. 在复制/移动操作中,通常将名称other用于其他对象。
  3. 一个错误:必须在ptr内放置一个值,这是不初始化变量的不正确做法。实际上,如果我们添加一个dtor并在此处使用swap惯用语(将在下面解释),它将进行无效的删除。
  4. 最后但并非最不重要的一点是,可以在活动对象上调用move ctor,而不是删除当前的ptr,而是将nullptr放在另一个对象上,这意味着永远不会删除它。例如,如果main是:
int main()
{
    CBuffer a{1};
    CBuffer b{2};
    a = std::move(b); // legal, but causes memory leak in your code, the value of a.ptr is never deleted!
}

交换习语如何帮助我们?!

让我们看看我的例子;当我们交换值(表示a.ptr = old b.ptrb.ptr = old a.ptr)时,无论何时删除b,现在驻留在b中的“旧” a.ptr都将被删除,因为我们只是交换了它们。通常,当我们使用move语义时,右值将很快被销毁,我们只是“骑乘”其销毁以防止内存泄漏。

您的代码应该看起来像这样(添加了一些图片以更好地理解):

class CBuffer{
private:
    int size = 0;
    int csize = 0;
    char* ptr = nullptr; // very important!!!
    char rtp = 0;
    int id = 0;

public:
    static int get_current_count() 
    { 
        static int object_cnt = 1;
        return object_cnt++; 
    }

    CBuffer(int size) : 
        size(size), 
        csize(0),
        ptr(new char[size]),
        rtp(0)
    {
        id = get_current_count();
        std::cout << "On ctor of " << id << std::endl;
        ptr[0] = 'a';
    }

    CBuffer(const CBuffer& other) : 
        size(other.size), 
        csize(other.csize), 
        ptr(new char[size]),
        id(get_current_count())
    {
        std::cout << "On copy ctor of " << other.id << " to " << this->id << std::endl;
        std::memcpy(this->ptr, other.ptr, size);
    }

    CBuffer(CBuffer&& other) :
        size(other.size),
        csize(other.csize),
        rtp(other.rtp), 
        id(get_current_count())
    {
        std::cout << "On move ctor of " << other.id << " to " << this->id << std::endl;
        std::swap(this->ptr, other.ptr);
    }

    ~CBuffer()
    {
        std::cout << "On dtor of " << id << std::endl;
        delete[] ptr;
    }
};

int main()
{
    CBuffer a = CBuffer(1);
    CBuffer b = std::move(a);
    CBuffer c = b;
}

输出为:

On ctor of 1
On move ctor of 1 to 2
On copy ctor of 2 to 3
On dtor of 3
On dtor of 2
On dtor of 1
© www.soinside.com 2019 - 2024. All rights reserved.