C++:将自动分配的对象添加到 std::vector

发布于 2024-11-11 04:15:33 字数 1895 浏览 3 评论 0 原文

我编写了以下代码:

#include <iostream>
#include <vector>
using namespace std;

class AClass
{
    public:
        int data;

        AClass() 
        { data = -333; cout << "+ Creating default " << data << endl; }

        AClass(const AClass &copy) 
        { data = copy.data; cout << "+ Creating copy of " << data << endl; }

        AClass(int d) 
        { data = d; cout << "+ Creating " << data << endl; }

        ~AClass() 
        { cout << "- Deleting " << data << endl; }

        AClass& operator = (const AClass &a)
        {  data = a.data; cout << "= Calling operator=" << endl; }
};

int main(void)
{
    vector<AClass> v;

    for (int i = 3; i--; )
        v.push_back(AClass(i));

    vector<AClass>::iterator it = v.begin();
    while (it != v.end())
        cout << it->data << endl, it++;

    return 0;
}

程序的输出是:

+ Creating 2
+ Creating copy of 2
- Deleting 2
+ Creating 1
+ Creating copy of 1
+ Creating copy of 2
- Deleting 2
- Deleting 1
+ Creating 0
+ Creating copy of 0
+ Creating copy of 2
+ Creating copy of 1
- Deleting 2
- Deleting 1
- Deleting 0
2
1
0
- Deleting 2
- Deleting 1
- Deleting 0

然后我将类更改为:

class AClass
{
    public:
        int data;

        AClass(int d) 
        { data = d; cout << "+ Creating " << data << endl; }

        ~AClass() 
        { cout << "- Deleting " << data << endl; }
};

输出变为:

+ Creating 2
- Deleting 2
+ Creating 1
- Deleting 2
- Deleting 1
+ Creating 0
- Deleting 2
- Deleting 1
- Deleting 0
2
1
0
- Deleting 2
- Deleting 1
- Deleting 0

看起来,当添加新对象时,向量正在复制现有对象,但似乎有很多不必要的东西正在进行分配/删除。这是为什么呢?另外,当我没有提供复制构造函数时,为什么第二个版本可以工作?

I wrote the following code:

#include <iostream>
#include <vector>
using namespace std;

class AClass
{
    public:
        int data;

        AClass() 
        { data = -333; cout << "+ Creating default " << data << endl; }

        AClass(const AClass ©) 
        { data = copy.data; cout << "+ Creating copy of " << data << endl; }

        AClass(int d) 
        { data = d; cout << "+ Creating " << data << endl; }

        ~AClass() 
        { cout << "- Deleting " << data << endl; }

        AClass& operator = (const AClass &a)
        {  data = a.data; cout << "= Calling operator=" << endl; }
};

int main(void)
{
    vector<AClass> v;

    for (int i = 3; i--; )
        v.push_back(AClass(i));

    vector<AClass>::iterator it = v.begin();
    while (it != v.end())
        cout << it->data << endl, it++;

    return 0;
}

And the output from the program is:

+ Creating 2
+ Creating copy of 2
- Deleting 2
+ Creating 1
+ Creating copy of 1
+ Creating copy of 2
- Deleting 2
- Deleting 1
+ Creating 0
+ Creating copy of 0
+ Creating copy of 2
+ Creating copy of 1
- Deleting 2
- Deleting 1
- Deleting 0
2
1
0
- Deleting 2
- Deleting 1
- Deleting 0

Then I changed the class to:

class AClass
{
    public:
        int data;

        AClass(int d) 
        { data = d; cout << "+ Creating " << data << endl; }

        ~AClass() 
        { cout << "- Deleting " << data << endl; }
};

And the output becomes:

+ Creating 2
- Deleting 2
+ Creating 1
- Deleting 2
- Deleting 1
+ Creating 0
- Deleting 2
- Deleting 1
- Deleting 0
2
1
0
- Deleting 2
- Deleting 1
- Deleting 0

It appears that vector is making copies of existing objects when new ones are added, but it seems like a lot of unnecessary allocation/deletion is taking place. Why is this? Also, why does the second version work when I haven't provided a copy constructor?

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

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

发布评论

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

评论(4

两仪 2024-11-18 04:15:33

当添加新对象时,向量似乎正在复制现有对象

当您添加元素时,例如使用 v.push_back(AClass(i));,所做的是临时 AClass 对象被创建并传递给 push_back。然后,push_back 必须将此对象复制到容器中。

您看到复制的另一个原因是 std::vector 将其元素连续存储在数组中。如果基础数组中没有剩余空间,并且您尝试在末尾添加另一个元素,则 std::vector 必须创建一个新数组,将旧数组中的元素复制到新数组中,然后在末尾插入新元素。如果您不希望发生这种情况,可以在开始插入元素之前调用 std::vector::reservestd::vector 中保留足够的空间,或者您可以使用不同的序列容器,例如 std::deque,它不连续存储其元素。

似乎发生了很多不必要的分配/删除

在 C++ 程序中,对象被频繁地创建和销毁。请注意,在您的程序中,AClass 的复制成本非常低:它的大小可能是四或八个字节,刚好足以容纳其 int 数据成员。

如果您有一个复制成本高昂的类型(例如,也许您有一个包含数千个节点的大型树数据结构),那么是的,复制可能太昂贵了。在这种情况下,您可以将智能指针存储在 std::vector 中动态分配的对象(例如 std::vector >) )。如果您的编译器支持右值引用并且具有移动感知标准库实现,则可以通过实现移动构造函数和移动赋值运算符并使用 emplace_back 而不是 来使复制成本高昂的类型可移动>push_back

当我没有提供复制构造函数时,为什么第二个版本可以工作?

如果您不声明复制构造函数,编译器会为您提供默认的复制构造函数。

It appears that vector is making copies of existing objects when new ones are added

When you add an element, e.g. with v.push_back(AClass(i));, what is done is a temporary AClass object is created and passed to push_back. push_back must then copy this object into the container.

The other reason that you see copies made is that std::vector stores its elements contiguously in an array. If there is no room left in the underlying array and you try to add another element to the end, the std::vector must create a new array, copy the elements from the old array into a new one, and then insert the new element at the end. If you don't want this to occur, you can call std::vector::reserve to reserve sufficient space in the std::vector before you start inserting elements, or you can use a different sequence container, like std::deque, which does not store its elements contiguously.

it seems like a lot of unnecessary allocation/deletion is taking place

In a C++ program, objects are frequently created and destroyed. Note that in your program, AClass is very cheap to copy: its size is probably four or eight bytes, just large enough to hold its int data member.

If you have a type that is expensive to copy (e.g., perhaps you have a large tree data structure that has thousands of nodes), then yes, copying may be too expensive. In that case, you can store smart pointers to dynamically allocated objects in the std::vector instead (a std::vector<shared_ptr<AClass> >, for example). If your compiler supports rvalue references and has a move-aware Standard Library implementation, you can make an expensive-to-copy type movable by implementing a move constructor and move assignment operator and using emplace_back instead of push_back.

why does the second version work when I haven't provided a copy constructor?

If you don't declare a copy constructor, the compiler provides a default copy constructor for you.

折戟 2024-11-18 04:15:33

Vector 使用 T 的常规数组作为其存储 - 当您创建其中一个数组时,它必须以某种方式初始化空间,唯一的选择是默认构造函数。稍后,当您设置索引的值时,它会将其复制到该空间上。

在第二个版本中,即使您没有提供复制构造函数,系统也会自动为您生成一个复制构造函数。如果您声明一个私有的,然后不实现它,您将看到编译器错误(因为您已经抑制了默认值的生成)

Vector uses a regular array of T as its store -- when you create one of these, it has to initialize the space somehow, and the only option is a default constructor. Later, when you set the value of an index, it copies it onto that space.

In the second version, even if you don't provide a copy constructor, one is generated for you automatically. If you declare a private one, and then don't implement it, you will see an compiler error (because you have suppressed the generation of the default)

小瓶盖 2024-11-18 04:15:33

您的对象被复制,因为矢量正在扩展其内部存储。如果您想避免复制,请提前调用 vector::reserve 来预分配内存。如果您不提供自己的复制构造函数,编译器将为您生成一个复制构造函数(复制所有成员的复制构造函数)。

Your objects are copied, because vector is expanding its internal storage. Call vector::reserve beforehand to preallocate memory, if you want to avoid the copies. If you don't provide your own copy ctor, compiler will generate one for you (one that copies all members).

不喜欢何必死缠烂打 2024-11-18 04:15:33

首先,如果您不提供复制构造函数,则它通常由c ++本身生成,并且向量正在复制所有数据,因为无论何时您要求它,都不确定您给他的变量是否具有有效值,例如,您可以使用一些局部变量并将其传递给向量,如果向量不复制你给它的内容,并且你返回该向量,则会出现一些内存违规。无论您向其中添加一些新对象,并且它需要一个更大的数组来存储所有对象,它都会分配一个新数组,然后将所有现有数据复制到新数组中。

first of all copy cunstructor isusualy generated by c++ itself if you don't provide one, and vector is copying all the data since it's not sure if the variable you gave him has valid value whenever you asked for it, for example you can use some local variable and pass it to the vector, if vector doesn't copy what you gave it, and you return that vector, there will be some memory violations. whever you add some new object to it and it needs a bigger array to store all the object it allocate a new array, and then copy all the existing data into the new array.

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