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

发布于 2024-08-20 08:44:41 字数 695 浏览 3 评论 0原文

这是代码:

#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”? 最后,输出是实现定义的还是还有其他可能的输出?

Here is the code:

#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;
}

And here is the output I got:

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

I understand that the output of the first line is from the call to the c-tor from when 'a' is created. One of the calls to the d-tor's also belongs to a.
What about the other three calls to A::~A(), where are they coming from?
And why are there more calls to the d-tor than calls to the c-tor?
How does the container clone 'a' when it adds copies to its elements?
And finally, is the output implementation-defined or are there are other possible outputs?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

烂人 2024-08-27 08:44:41

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

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

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

You need to add a copy constructor:

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

The vector, like all other Standard Library containers, stores copies - these copies are made with the copy constructor. You should be aware however that there are several places where the compiler is allowed to elide copy construction, or even make extra copies, so your output may not be exactly what you are expecting.

老旧海报 2024-08-27 08:44:41

要了解发生的情况,您在 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)自行处理块。

To understand what happens, you are missing one method in A :

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

Then you see the output:

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

What happen is that, for each push_back the vector allocate a new contiguous array, copy the old content, and destroy it. If you count, the first copy constructor is for the first push_back, the second and third for the next push_back. The first destructor is for the second push_back, the two next for the destruction of the vector, the last one for the destruction of the variable a.

And by the way, this is completely implementation defined, as it is allowed to allocate by chunk, which would prevent quite a few copy/destruction. You can even so the chunks yourself by using vector::reserve(size_type n).

苍景流年 2024-08-27 08:44:41

我确信您意识到您正在堆栈上创建“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()

由于仅创建了该对象的一个​​实例,并且该数组仅存储指针的副本。显然,在某些时候,您需要通过对象的指针之一删除对象本身,以确保最终收回内存。

As I'm sure you realise you are creating your "A" objects on the stack and they are then being copied into the array (as the other answers suggest) implicately using the copy constructor.

If your A objects are real data objects with data they own, or complex state that is difficult to copy you might want to consider storing pointers in your array rather than storing the objects directly. You will need to manage the memory yourself then, but it's a point worth considering.

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

You would see the output:

A()

Since only one instance of the object has been created and the array is just storing copies of the pointer. Obviously, at some point you would need to delete the object itself via one of its pointers to ensure you get the memory back eventually.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文