需要帮助了解STL向量(消息正文中的简单代码)

时间:2010-02-07 12:19:30

标签: c++ stl vector

以下是代码:

#include <vector>
#include <iostream>

class A
{
public:
    A() { std::cout << __FUNCTION__ << "\n"; }
    ~A() { std::cout << __FUNCTION__ << "\n"; }

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

int main(int argc, char* argv[])
{
    std::vector<A> as;
    A a;
    as.push_back(a);
    as.push_back(a);
    return 0;
}

这是我得到的输出:

A::A
A::~A
A::~A
A::~A
A::~A

据我所知,第一行的输出来自于创建“a”时对c-tor的调用。其中一个对d-tor的调用也属于a。 对A ::〜A()的其他三个调用怎么样,它们来自哪里? 为什么有更多的呼叫到d-tor比呼叫c-tor? 容器在将副本添加到元素时如何克隆'a'? 最后,是输出实现定义还是有其他可能的输出?

3 个答案:

答案 0 :(得分:3)

您需要添加复制构造函数:

 A( const A& ) { std::cout << __FUNCTION__ << "\n"; }

与所有其他标准库容器一样,该向量存储副本 - 这些副本是使用复制构造函数创建的。但是您应该知道,有几个地方允许编译器忽略复制构造,甚至制作额外的副本,因此您的输出可能与您期望的完全不同。

答案 1 :(得分:2)

要了解会发生什么,您在A:

中缺少一种方法
A(const A&) { std::cout << __FUNCTION__ << "(const A&)\n"; }

然后你看到输出:

A()
A(const A&)
A(const A&)
A(const A&)
~A
~A
~A
~A

对于每个push_back,向量分配一个新的连续数组,复制旧内容并销毁它。如果算一算,第一个拷贝构造函数用于第一个push_back,第二个和第三个用于下一个push_back。第一个析构函数用于第二个push_back,两个用于销毁向量,最后一个用于销毁变量a。

顺便说一句,这是完全实现定义的,因为它允许按块分配,这可以防止相当多的复制/破坏。您甚至可以使用vector::reserve(size_type n)来自行调整块。

答案 2 :(得分:0)

我确信您已经意识到您正在堆栈中创建“A”对象,然后使用复制构造函数将它们复制到数组中(正如其他答案所示)。

如果您的A对象是包含他们拥有的数据的真实数据对象,或者是难以复制的复杂状态,您可能需要考虑在数组中存储指针而不是直接存储对象。你需要自己管理内存,但这是值得考虑的一点。

int main(int argc, char* argv[])
{
    std::vector<A*> as;
    A *a = new A();
    as.push_back(a);
    as.push_back(a);
    return 0;
}

你会看到输出:

A()

由于只创建了一个对象实例,而该数组只是存储指针的副本。显然,在某些时候你需要通过它的一个指针删除对象本身,以确保最终获得内存。