插入向量时的 C++ 临时对象

c++'s temporary objects when inserted to a vector

本文关键字:C++ 临时对象 向量 插入      更新时间:2023-10-16

我正试图让这段代码正常工作,但对象不断被破坏。。。我发现这与对象被复制到向量有关,但找不到任何方法来阻止它…

#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Obje
{
private:
    static int instances;
    int id;
public:
    static int getInstances();
    void getId();
    virtual void myClass();
    Obje(int auxId);
    ~Obje();
};
int Obje::instances = 0;
int Obje::getInstances()
{
    return instances;
}
Obje::Obje(int auxId)
{
    this->id = auxId;
    cout << "Obje Created." << endl;
    Obje::instances++;
}
Obje::~Obje()
{
    cout << "Obje Destroyed." << endl;
    Obje::instances--;
}
void Obje::myClass()
{
    cout << "Obje." << endl;
}
void Obje::getId()
{
    cout << this->id << endl;
}
int main()
{
    vector <Obje> list;
    Obje *a = new Obje(59565);
    list.push_back(*a);
    Obje *b = new Obje(15485);
    list.push_back(*b);
    for(vector<Obje>::iterator it = list.begin(); it != list.end(); ++it)
    {
        it->getId();
    }
    return 0;
}

它生成以下输出:

Obje Created.
Obje Created.
Obje Destroyed.
59565
15485
Obje Destroyed.
Obje Destroyed.

我所看到的T(const T& new);是什么意思?

首先,在堆中分配对象而不使用智能指针并忘记delete是一种糟糕的做法。尤其是当您创建它只是为了复制它时。

CCD_ 3在向量中创建CCD_ 4的副本。要在矢量中创建一个项而不复制另一个项,可以执行list.emplace_back(/*constructor parameters*/);,它可从c++11获得。(参见http://en.cppreference.com/w/cpp/container/vector/emplace_back)

因此,为了使结果行为符合您的期望,您应该进行

    vector <Obje> vec;
    vec.emplace_back(59565);
    vec.emplace_back(15485);
    for(const auto & item : vec)
    {
        item.getId();
    }

顺便说一句,将向量称为列表也是一种非常糟糕的做法,因为列表是不同的容器类型,读取这样的代码可能会有点混乱。我想,我开始很烦人了,但最好将方法getId调用为showId,因为现在它什么都不返回。

关于堆、new和指针的使用,请参阅我在您的问题中的评论。

关于问题对象被销毁,vector维护一个内部缓冲区来存储对象。当您将push_back新对象vector时,如果其内部缓冲区已满,它将(此处不提及异常发生时将执行的内容):

  1. 分配新的内部缓冲区,该缓冲区足够大以存储其新数据
  2. 将数据从旧的内部缓冲区移动到新的内部缓冲区时
  3. 销毁旧缓冲区

因此,在这种情况下,您的对象将被销毁并复制到新位置,因此复制构造函数会让您更清楚。

p/S:AFAIK,一些编译器通过memmovestd::move 移动数据