C语言中如何移动语义为?

摘要:移动语义 移动语义让事情变得简单,移动语义本质上允许我们移动对象。这在C++11之前是不可能的,因为C++11引入了右值引用,这是移动语义所必须的。基本思想是,当我们写
移动语义 移动语义让事情变得简单,移动语义本质上允许我们移动对象。这在C++11之前是不可能的,因为C++11引入了右值引用,这是移动语义所必须的。基本思想是,当我们写C++代码时,有很多情况下,我们不需要或者不想把一个对象从一个地方复制到另一个地方,但又不得不复制,因为这是唯一可以复制的地方。 例如: 我们把一个对象传递给一个函数,那么它要获得那个对象的所有权,我没有选择,只能拷贝。 当我想从函数返回一个对象时也是一样,我仍然需要在函数中创建那个对象,然后返回它,也就是说又需要复制对象。 现在我不喜欢用返回值作为例子,因为因为有一种叫做返回值优化的东西对这部分进行了优化,让它不再是个问题。但是在第一个例子中,如果我需要传入一个对象,这个对象放入某个函数,而这个函数需要得到这个对象的所有权或者其它,我仍然需要在当前堆栈中构造一个一次性对象,不管它在哪里,然后将它复制到我正在调用的函数中,而这并不理想。因为我在这里不需要它,而是在那里需要,但我又不能在那里构造它,因为我需要先在这里构造它,然后把它传递进去,它变得一团糟。 当然,如果你的对象只是由一对整数或类似的东西组成,那复制也没什么大不了的,但如果你的对象需要堆分配内存之类的(比如:一个字符串,如果你需要复制它,你需要创建一个全新的堆空间),这就不好了,这会成为一个沉重的复制对象,这正是移动语义的用武之地。 如果我们只是移动对象,而不是复制它,那么性能会更高。可以类比剪切和复制的区别。 #include<iostream> #include<string> //1. 自定义一个被操作的类 class String { private: uint32_t m_Size; char* m_Data; public: String() = default; String(const char* string) { printf("Created!\n"); m_Size = strlen(string); m_Data = new char[m_Size]; memcpy(m_Data, string, m_Size); } //拷贝构造函数 String(const String& other) { printf("Copied!\n"); m_Size = other.m_Size; m_Data = new char[m_Size]; memcpy(m_Data, other.m_Data, m_Size); } //move构造函数,只接收一个右值,意思是一个临时值 //noexcept: 它不应该抛出异常,并不是经常使用它,但是为了保证绝对正确,我们会这样做 //通过指定这个构造函数,希望最终当我们执行这个“复制”构造函数时,不会复制。而是变成 移动了 String(String&& other) noexcept { printf("Moved!\n"); m_Size = other.m_Size; //这里不再复制,而是重新指向参数传过来的数据地址,所以没有复制 m_Data = other.m_Data; //但是这个是移动复制构造函数,所以有2个String实例,而第二个的实际数据指针也指向第一个的数据地址。
阅读全文