【问题标题】:c++'s temporary objects when inserted to a vectorc++ 插入向量时的临时对象
【发布时间】:2015-12-14 05:39:10
【问题描述】:

我正在尝试使此代码正常工作,但对象不断被破坏... 我发现它与被复制到向量的对象有关,但找不到任何方法来阻止它......

#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&amp; new); 是什么意思?

【问题讨论】:

  • T(const T&amp;obj);复制构造函数。查一下。
  • 首先,您需要阅读this comment,然后阅读this question,以了解如何在C++中使用内存。这是 C++ 而不是 Java。
  • 这里不需要任何new 表达式。他们只会为您制造 nemory 泄漏。 C++ 不是 Java。
  • 不使用 new 我有 5 次调用析构函数...我如何实现这个复制构造函数?
  • 当然析构函数最终必须被执行!怎么了?

标签: c++


【解决方案1】:

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

list.push_back(*a); 在向量中创建*a 的副本。要在向量中创建一个项目而不复制另一个项目,您可以执行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,因为现在它什么都不返回。

【讨论】:

  • emplace_back 在 C++11 中可用,我认为应该备注一下。
  • @HrejWaltz 使用最新的 Eclipse 和 GCC,Project->properties->C/C++ Build->Settings->GCC C++ compiler->Dialect->Language Standard Drop-down。
  • emplace_back() keep unresolved... 完成并在 c/c++ 编译器中添加标志->杂项...
【解决方案2】:

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

关于问题对象被销毁,vector 维护一个内部缓冲区来存储对象。当你push_back 新对象到vector 时,如果它的内部缓冲区已满,它就会(发生异常时执行的东西这里就不说了):

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-14
    • 2017-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-24
    相关资源
    最近更新 更多