【问题标题】:Why memory is new when doing std::move为什么做 std::move 时内存是新的
【发布时间】:2017-06-27 21:19:57
【问题描述】:

在这段代码中:

int main()
{
    std::vector<int> src{1, 2, 3};

    std::cout << "src: ";
    for (std::vector<int>::const_iterator x = src.begin(); x != src.end(); ++ x)
    {
        std::cout << *x << ' ' << &(*x) << std::endl ;
    }   

    std::vector<int> dest(std::move(src));

    std::cout << "src: ";                                                       
    for (std::vector<int>::const_iterator x = src.begin(); x != src.end(); ++ x)
    {
         std::cout << *x << ' ' << &(*x) << std::endl ;;
    }   
    std::cout << "\ndest: ";
    for (std::vector<int>::const_iterator x = dest.begin(); x != dest.end(); ++ x)
    {
        std::cout << *x << ' ' << &(*x) << std::endl ;;
    }   
    std::cout << '\n';
}

src: 1 0x43ea7d0
2 0x43ea7d4
3 0x43ea7d8
src: 
dest: 1 0x43ea7d0
2 0x43ea7d4
3 0x43ea7d8

这是有道理的,因为 dest 的内存地址现在是之前 src 的地址。

但是当我这样做时:

int main()
{
    std::vector<int> src{1, 2, 3};
    std::vector<int> dest(src.size());

    std::cout << "src: " << std::endl;
    for (std::vector<int>::const_iterator x = src.begin(); x != src.end(); ++ x)
    {
        std::cout << *x << ' ' << &(*x) << std::endl ;
    }   
    std::cout << "\ndest: " << std::endl;
    for (std::vector<int>::const_iterator x = dest.begin(); x != dest.end(); ++ x)
    {
        std::cout << *x << ' ' << &(*x) << std::endl ;
    }    
    std::cout << '\n';

    std::move_backward(src.begin() , src.end(), dest.end());

    std::cout << "src: " << std::endl;
    for (std::vector<int>::const_iterator x = src.begin(); x != src.end(); ++ x)
    {
        std::cout << *x << ' ' << &(*x) << std::endl ;
    }   
    std::cout << "\ndest: " << std::endl;
    for (std::vector<int>::const_iterator x = dest.begin(); x != dest.end(); ++ x)
    {
        std::cout << *x << ' ' << &(*x) << std::endl ;
    }    
    std::cout << '\n';
}

   src: 
1 0x41e0140
2 0x41e0144
3 0x41e0148

dest: 
0 0x41e0160
0 0x41e0164
0 0x41e0168

src: 
1 0x41e0140
2 0x41e0144
3 0x41e0148

dest: 
1 0x41e0160
2 0x41e0164
3 0x41e0168

为什么第二种情况地址不同?我以为 std::move 只是改变指针,而不触及原始对象的内存

【问题讨论】:

  • move_backward 正在移动迭代器指定的范围内的 items,而不是范围的容器本身。尝试使用带有可移动物品的范围。
  • en.cppreference.com/w/cpp/algorithm/move_backward 参见可能的实现部分,您会看到它正在移动元素本身,而不是容器

标签: c++ c++11


【解决方案1】:

您的第一个代码示例会移动向量本身。这会将源向量的内容移动到目标向量,而不是触及包含的元素。

您的第二个代码示例创建一个与源大小相同的新向量(使用默认构造元素),然后将分配移动到这些元素。

当你使用一个元素类型来告诉你用它做了什么时,这一点变得很明显:

#include <iostream>
#include <vector>
#include <algorithm>


struct Thing {
    Thing() {}
    Thing & operator=(Thing &&) { std::cout << "Moved a thing" << std::endl; }
};


int main() {
    std::vector<Thing> source1(1);
    std::vector<Thing> source2(1);

    std::cout << "Move vector:" << std::endl;
    std::vector<Thing> vector_moved{std::move(source1)};

    std::cout << "-------------" << std::endl;

    std::cout << "Move elements:" << std::endl;
    std::vector<Thing> elements_moved{source2.size()};
    std::move_backward(source2.begin() , source2.end(), elements_moved.end());

    return 0;
}

Output:

Move vector:
-------------
Move elements:
Moved a thing

【讨论】:

    猜你喜欢
    • 2014-02-16
    • 2021-11-13
    • 2021-05-07
    • 2012-07-28
    • 2020-08-06
    • 2011-03-25
    相关资源
    最近更新 更多