首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >移动语义的机制

移动语义的机制
EN

Stack Overflow用户
提问于 2020-03-29 20:41:17
回答 1查看 57关注 0票数 0

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

如果是这样,为什么在下面的代码中

代码语言:javascript
复制
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;

台词

代码语言:javascript
复制
std::cout << &this->ptr << std::endl;
std::cout << &source.ptr << std::endl;

是否打印不同的地址?

EN

回答 1

Stack Overflow用户

发布于 2020-03-29 22:57:03

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

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

我在代码中添加了一些东西:

  1. 我已经初始化了初始化器列表中的所有变量。此外,我还删除了拷贝函数中硬编码的大小初始化。在copy/move operations.
  2. An中使用other作为其他对象是很常见的错误:
  3. a value in the ptr,这是一个不初始化你的变量的坏习惯。实际上,如果我们添加一个dtor,并在这里使用交换习惯用法(在下面解释),它会造成无效的删除。最后但并非最不重要的是,可以在活动对象上调用
  4. ,而不是删除当前的ptr,而是将nullptr放在other上,这意味着永远不会删除它。例如,如果main是:

代码语言:javascript
复制
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也会被删除,因为我们刚刚交换了它们。通常,当我们使用移动语义时,r值很快就会被销毁,我们只是“骑”在它的销毁上,以防止内存泄漏。

您的代码应该是这样的(为了更好地理解,添加了一些打印):

代码语言:javascript
复制
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;
}

输出结果为:

代码语言:javascript
复制
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
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60914428

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档