c++ - 从堆栈移动到堆、向量和数组
问题描述
我制作了两个简单的程序,尝试从不同的记忆中转移东西。
一个是使用存储在堆上的向量,另一个是数组。运行这些示例后,我不明白输出。
我喜欢将移动运算符视为指针之间的交换,我可能是错的,但如果堆 ptr 从堆栈中接收到一个指针,当它被清除时,堆 ptr 将指向任何有价值的东西,除非完成了 deap 副本?
带矢量:
#include <iostream>
#include <utility>
#include <vector>
#include <array>
#include <string>
using namespace std;
struct Bitmap {
Bitmap() {}
Bitmap(string n) : name(n) {}
Bitmap(const Bitmap& other) {
name = other.name;
std::cout << "copy constructor" << std::endl;
}
Bitmap& operator=(const Bitmap& other) {
name = other.name;
std::cout << "assignment operator" << std::endl;
}
Bitmap(Bitmap&& other) {
name = move(other.name);
std::cout << "move constructor" << std::endl;
}
string name;
};
struct BitmapContainer {
BitmapContainer() {}
std::vector<Bitmap> data;
};
int main() {
BitmapContainer stackContainer;
BitmapContainer* heapContainer = new BitmapContainer();
Bitmap test;
Bitmap test2;
Bitmap* test3 = new Bitmap();
std::cout << "only on stack" << std::endl;
stackContainer.data.push_back(move(test));
std::cout << "stack to heap" << std::endl;
heapContainer->data.push_back(move(test2));
std::cout << "heap to heap" << std::endl;
heapContainer->data.push_back(move(*test3));
}
输出:
only on stack
move constructor
stack to heap
move constructor
heap to heap
move constructor
copy constructor
2 第一次移动意味着可以将对象从一个内存移动到另一个内存,即使我的向量在堆上,第一个应该像第二个一样失败。而且我不明白为什么我在最后调用了一个复制构造函数。
现在,如果我改用数组:
struct BitmapContainer {
BitmapContainer() {}
std::array<Bitmap, 2> data;
};
int main() {
BitmapContainer stackContainer;
BitmapContainer* heapContainer = new BitmapContainer();
Bitmap test;
Bitmap test2;
Bitmap* test3 = new Bitmap();
std::cout << "only on stack" << std::endl;
stackContainer.data[0] = move(test);
std::cout << "stack to heap" << std::endl;
heapContainer->data[0] = move(test2);
std::cout << "heap to heap" << std::endl;
heapContainer->data[1] = move(*test3);
}
输出:
only on stack
assignment operator
stack to heap
assignment operator
heap to heap
assignment operator
只是副本,不知道为什么。
解决方案
而且我不明白为什么最后会调用一个复制构造函数。
当向量重新分配时使用复制构造函数,这意味着它的容量已满,并且没有更多空间可以在末尾插入新的(推回)元素。重新分配基本上是分配一个新的内存空间并从原始内存中“移动”实际元素。
但是,在您的情况下,此“移动”是通过复制构造器实现的。原因是您的移动构造函数不是noexcept
,并且在这里std::vector
更喜欢强大的异常保证而不是性能。
如果您创建您的Bitmap::Bitmap(Bitmap&&)
构造函数,则将使用noexcept
移动构造函数。您可以安全地执行此操作,因为 的移动构造函数保证为.std::string
noexcept
为了使比较公平,要么在两种情况下使用不同的向量,要么reserve
预先为两个元素使用一个内存。
至于数组,您没有为Bitmap
. 因此,除了使用定义的复制赋值运算符来分配数组元素外,别无选择。使用std::move
不能改变任何事情。
推荐阅读
- php - 如何在 PHP 中抛出警告?
- php - 如何使用php在数据库中显示分数列?
- c - How to Find Most Significant Bit Position?
- javascript - Detect which section is in view
- rx-java - RxJava:如何在将第一项发送给观察者之前只修改第一项
- json - 使用 Angular 和商店在本地 db.json 上创建一个 http 请求
- c# - How to get the entities from generic EntitySet on run-time without knowing the generic type?
- javascript - 反应原生:草图画布中未定义的 UIManager
- javascript - 水平图表中的标记项目与创建的详细信息可视化匹配
- sql-server - Storage of Bit columns for null values?