当前位置: 首页 > 知识库问答 >
问题:

如何使用std::移动和更新向量大小从向量中删除最后一项

朱雅惠
2023-03-14
#include <iostream>
#include <exception>
#include <stdexcept>
#include <string>
#include <vector>
#include <utility>
     
struct Foo {
    Foo(std::string t):text(t){}
    //destructor deleted
        
    std::string text;
};

int main()
{
    std::vector<Foo> v;
        
    v.push_back(Foo("foo 1"));
    v.push_back(Foo("foo 2"));
    v.push_back(Foo("foo 3"));
      
    for(auto& foo : v){
        std::cout<<foo.text<<"\n";
    }
      
    Foo fooBack = std::move(v.back());
      
    std::cout<<fooBack.text<<"\n";
      
    for(auto& foo : v){
        std::cout<<foo.text<<"\n";
    }
}

std::move()在本例中不会窃取返回变量。有没有办法避免多余的副本?

这就是结果:

foo 1
foo 2
foo 3
foo 3
foo 1
foo 2
foo 3

基于建议的新代码(不知道是否一直在同一个线程上询问,不知道这是否是我所期望的,我所做的这一切都是为了减少代码):

#include <iostream>
#include <exception>
#include <stdexcept>

#include<string>
#include<vector>
#include<utility>
 
struct Foo {
        Foo(std::string t):text(t){
            std::cout<<text<<" construct foo called \n";
        }
        Foo(const Foo& f){
            text = f.text;
            std::cout<<text<<"copy construct foo called \n";
        }
        Foo(Foo&& f){
            text = std::move(f.text);
            std::cout<<text<<"move construct foo called \n";
        
        }
        /*
    ~Foo() {
    }
    */
    
    std::string text;
};
int main()
{
    
    std::vector<Foo> v;
    
  v.emplace_back("foo 1");
  v.emplace_back("foo 2");
  v.emplace_back("foo 3");
  
  for(auto&& foo : v){
    std::cout<<foo.text<<"\n";
  }
  
  Foo fooBack = std::move(v.back());
  v.pop_back();
  
  std::cout<<fooBack.text<<"\n";
  
  for(auto&& foo : v){
    std::cout<<foo.text<<"\n";
  }
  
}

看到它在行动中的新结果

foo 1 construct foo called 
foo 2 construct foo called 
foo 1copy construct foo called 
foo 3 construct foo called 
foo 1copy construct foo called 
foo 2copy construct foo called 
foo 1
foo 2
foo 3
foo 3move construct foo called 
foo 3
foo 1
foo 2

共有1个答案

萧星火
2023-03-14

语句foo fooBack=std::move(v.back());根本不会从向量中删除最后一个foo对象,但它确实会将该对象的内容移动到fooBack变量中,这是因为编译器为foo生成了一个移动构造函数。但是,原始的foo对象本身仍然在向量中,这就是为什么您的第二个for循环仍然看到该对象的原因。对象可能不再有text值可打印,因为fooback窃取了它。

现场演示

话虽如此,但在您的情况下,std::String可能是在利用“短字符串优化”(将小字符串值保留在std::String类本身的固定缓冲区中,以避免在不需要时动态分配内存),从而使从一个std::String“移动”到另一个std::String只会复制该固定缓冲区的数据,保持原始std::String不变。这就解释了为什么在将v.back()“移动”到fooback变量之后,第二个for循环仍然在向量中显示“foo 3”-这实际上是一个复制,而不是移动。

如果要实际从向量中删除最后一个foo对象,则可以使用v.pop_back()进行此操作,例如:

Foo fooBack = std::move(v.back());
v.pop_back(); // <-- add this

现场演示

需要注意的是,您的push_back()应该使用emplace_back(),以避免创建临时的foo对象,这些对象必须在推送过程中移除:

//v.push_back(Foo("foo 1"));
//v.push_back(Foo("foo 2"));
//v.push_back(Foo("foo 3"));
v.emplace_back("foo 1");
v.emplace_back("foo 2");
v.emplace_back("foo 3");
 类似资料:
  • 这应该很容易,但我一直在撞我的头。 我有数字向量 我有一个数值向量v2。v2始终是v1的子集。 我想从v1中删除v2中的所有元素,但每个v2元素只删除一个(而且完全是一个)v1元素。 所需输出 如果我希望将保留在v1之外。使用很容易。 如果我希望将与v1保持一致。此外,也能起到作用。 如果我希望将与v1保持一致。现在返回。不是我想要的。 当答案输入时,我很可能会用头撞我的键盘,但现在我还没有得到最

  • 我有一个整数向量: 考虑到将始终为偶数。 我只是想把相邻的元素转换成一对,像这样: i、 两个相邻的元件连接成一对。 我可以使用什么STL算法轻松实现这一点?有没有可能通过一些标准算法来实现这一点? 当然,我可以很容易地编写一个旧的索引for循环来实现这一点。但我想知道,使用基于范围的for循环或任何其他STL算法(如等)最简单的解决方案是什么样的。

  • 我想知道v1.swap(v2)使用std::交换(v1, v2)有什么好处。 从性能角度来看,我已经实现了一个简单的测试代码(我不确定它是否相关): 根据输出,向量::swap似乎在没有优化的情况下更快-O0。输出为(微秒): 与-O3没有显著差异。

  • 问题内容: 遵循“只有一种明显的方法”,如何在Numpy中获得向量(一维数组)的大小? 上面的方法有效,但是我 不敢相信 自己必须指定这样一个琐碎的核心功能。 问题答案: 您需要的功能是。(我认为它应该作为数组的属性存在于基本numpy中-说-但很好)。 您还可以根据需要输入可选的n阶范数。假设您想要1范数: 等等。

  • 让我们在一个示例中展示它,其中我们有一个包含主数据的数据类,某种指向主数据的索引,我们还需要公开索引的版本。 这是错误的,因为用户可以轻松修改数据: 这样做的原因是,Data::getIndex应该返回的正确类型是: 但是,您可以猜测,当您尝试以这种方式编写方法以“将非常量变量转换为常量变量”时会发生什么: 据我所知,C没有解决这个问题的好方法。显然,我可以创建新的向量,从索引中复制值并返回它,但

  • 本文向大家介绍如何找到R中向量的最小值和最大值的索引?,包括了如何找到R中向量的最小值和最大值的索引?的使用技巧和注意事项,需要的朋友参考一下 在分析项目中进行数据探索时,有时我们需要找到一些值的索引,主要是最小值和最大值的索引,以检查相应的数据行是否包含一些关键信息,或者我们可能会忽略它。此外,如果我们不想忽略它们,有时会根据数据特征将这些值转换为另一个值。 示例