看起来 std::move_iterator 只适用于字符串数据类型

问题描述 投票:0回答:1

如果容器具有字符串类型的数据,则可以使用

std::move_iterator
将数据从源容器移动到目标容器。
std::move_iterator
不与容器中的其他数据类型一起操作。

std::move_iterator 工作正常

#include <iostream>     // std::cout
#include <iterator>     // std::move_iterator
#include <vector>       // std::vector
#include <string>       // std::string
#include <algorithm>    // std::copy

using namespace std;
int main () {
    
    vector<string>src = {"one", "two", "three", "four"}, des(4);
    using Iter = vector<string>::iterator;
    
    //move the data from src to des
    move_iterator<Iter>beginitr(src.begin());
    move_iterator<Iter>enditr(src.end());
    Iter diter = des.begin();
    
    while(beginitr != enditr)
    {
        *diter++ = *beginitr++;
    }
    
    cout << "src container size: " << src.size() << endl;
    cout << "data: " ;
    for_each(begin(src),end(src), [](string x){cout << x ;});
    cout << endl << "THE END";

  return 0;
}

输出

src container size: 4
data: 
THE END

std::move_iterator 不移动数据

#include <iostream>     // std::cout
#include <iterator>     // std::move_iterator
#include <list>       // std::vector
#include <string>       // std::string
#include <algorithm>    // std::copy

using namespace std;
int main () {
    
    list<int>src = {1,2,3,4}, des(4);
    using Iter = list<int>::iterator;
    
    //move the data from src to des
    move_iterator<Iter>beginitr = make_move_iterator(src.begin());
    move_iterator<Iter>enditr = make_move_iterator(src.end());
    Iter diter = des.begin();
    
    while(beginitr != enditr)
    {
        *diter++ = *beginitr++;
    }
    
    cout << "src container size: " << src.size() << endl;
    for_each(begin(src),end(src), [](int x){cout << x << endl;});
    

  return 0;
}

输出

src container size: 4
1
2
3
4

看起来整数数据被复制到目标容器而不是被移动。

c++ iterator c++17 stdvector move-semantics
1个回答
0
投票

使用移动迭代器的唯一区别是取消引用迭代器会产生右值引用。如果只有复制赋值运算符可用,但没有移动赋值运算符,则这将用作“后备”。

以下代码演示了这一点:

#include <algorithm>
#include <iostream>
#include <iterator>
#include <list>
#include <utility>

struct Test
{
#if 0
    Test(Test&&)
    {
        std::cout << "Test::Test(Test&&)\n";
    }

    Test& operator=(Test&&)
    {
        std::cout << "Test& Test::operator=(Test&&)\n";
        return *this;
    }
#endif 
    
    Test(Test const&)
    {
        std::cout << "Test::Test(Test const&)\n";
    }

    Test& operator=(Test const&)
    {
        std::cout << "Test& Test::operator=(Test const&)\n";
        return *this;
    }

    Test()
    {
        std::cout << "Test::Test()\n";
    }

};

 
int main() {
    std::list<Test> src(4);
    std::list<Test> des(4);

    std::cout << "-------------------copy with move iterator--------------------\n";
    std::copy(std::make_move_iterator(src.begin()), std::make_move_iterator(src.end()), des.begin());

    std::cout << "-------------------copy with normal iterator--------------------\n";
    std::copy(src.begin(), src.end(), des.begin());
}

输出

#if 0
保持原样:

...
-------------------copy with move iterator--------------------
Test& Test::operator=(Test const&)
Test& Test::operator=(Test const&)
Test& Test::operator=(Test const&)
Test& Test::operator=(Test const&)
-------------------copy with normal iterator--------------------
Test& Test::operator=(Test const&)
Test& Test::operator=(Test const&)
Test& Test::operator=(Test const&)
Test& Test::operator=(Test const&)

定义了移动语义的输出(

#if 1
而不是
#if 0
):

...
-------------------copy with move iterator--------------------
Test& Test::operator=(Test&&)
Test& Test::operator=(Test&&)
Test& Test::operator=(Test&&)
Test& Test::operator=(Test&&)
-------------------copy with normal iterator--------------------
Test& Test::operator=(Test const&)
Test& Test::operator=(Test const&)
Test& Test::operator=(Test const&)
Test& Test::operator=(Test const&)

Godbolt 演示

对于像

int
这样的算术类型,只有复制语义,没有移动语义,不会在代码中修改源列表。

© www.soinside.com 2019 - 2024. All rights reserved.