首页 > 解决方案 > 从堆栈移动到堆、向量和数组

问题描述

我制作了两个简单的程序,尝试从不同的记忆中转移东西。

一个是使用存储在堆上的向量,另一个是数组。运行这些示例后,我不明白输出。

我喜欢将移动运算符视为指针之间的交换,我可能是错的,但如果堆 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

只是副本,不知道为什么。

标签: c++memory

解决方案


而且我不明白为什么最后会调用一个复制构造函数。

当向量重新分配时使用复制构造函数,这意味着它的容量已满,并且没有更多空间可以在末尾插入新的(推回)元素。重新分配基本上是分配一个新的内存空间并从原始内存中“移动”实际元素。

但是,在您的情况下,此“移动”是通过复制构造器实现的。原因是您的移动构造函数不是noexcept,并且在这里std::vector更喜欢强大的异常保证而不是性能。

如果您创建您的Bitmap::Bitmap(Bitmap&&)构造函数,则将使用noexcept移动构造函数。您可以安全地执行此操作,因为 的移动构造函数保证.std::stringnoexcept

为了使比较公平,要么在两种情况下使用不同的向量,要么reserve预先为两个元素使用一个内存。


至于数组,您没有Bitmap. 因此,除了使用定义的复制赋值运算符来分配数组元素外,别无选择。使用std::move不能改变任何事情。


推荐阅读