简体   繁体   English

std::emplace_back 调用向量中其他对象的构造函数?

[英]std::emplace_back invoking constructor of other objects in vector?

I am really confused about std::vector::emplace_back .我真的对std::vector::emplace_back感到困惑。 I run the following code:我运行以下代码:

struct Thing {
    explicit Thing(std::string name) : name_{std::move(name)} {
        std::cout << "Constructed a thing called " << name_ << std::endl;
    }

    ~Thing() {
        std::cout << "Deconstructed a thing called " << name_ << std::endl;
    };
    std::string name_;
};


int main() {
    std::vector<Thing> things{Thing("A")};
    std::cout << "Size: " << things.size() << std::endl;
    things.emplace_back("B");
    std::cout << "Size: " << things.size() << std::endl;
}

and get this output:并得到这个输出:

Constructed a thing called A
Deconstructed a thing called A
Size: 1
Constructed a thing called B
Deconstructed a thing called A
Size: 2
Deconstructed a thing called A
Deconstructed a thing called B

Why on earth does things.emplace_back("B") invoke the deconstructor of the thing called A? things.emplace_back("B")为什么things.emplace_back("B")调用名为 A 的事物的解构器?

std::vector stores the objects continuously in an allocated memory block. std::vector将对象连续存储在分配的内存块中。 When that block's size becomes too small to add new elements into it, it must allocate a new, larger, memory block and copy/move the currently present elements in the vector into that new allocation.当该块的大小变得太小而无法向其中添加新元素时,它必须分配一个新的更大的内存块,并将向量中当前存在的元素复制/移动到该新分配中。 After that, the objects in the previous allocation are destroyed, involving the destructor call.之后,之前分配中的对象被销毁,涉及析构函数调用。

You are not seeing the copies being made, because you didn't define a custom copy constructor.您没有看到正在制作的副本,因为您没有定义自定义复制构造函数。 If you did, you would see that a copy of A is copy constructed before the original A is destructed.如果你这样做了,你会看到A的副本是在原始A被破坏之前复制构造的。 If you define a noexcept move constructor, you will see that a copy of A is move constructed before the original A is destructed.如果定义noexcept移动构造函数,您将看到在原始A被破坏之前构造了A的副本。

What's happening is that when you add B to the vector, the vector probably only had capacity for 1 element, so had to move it's existing element into another vector (destructing the one in the original storage)发生的事情是,当您将B添加到向量时,向量可能只有 1 个元素的容量,因此必须将其现有元素移动到另一个向量中(破坏原始存储中的元素)

Let's add some more logging to see what happens:让我们添加更多日志来看看会发生什么:

#include <iostream>
#include <string>
#include <vector>

struct Thing {
    explicit Thing(std::string name) : name_{std::move(name)} {
        std::cout << "Constructed a thing called " << name_ << " at " << this << std::endl;
    }
    Thing(Thing&& t) noexcept : name_{std::move(t.name_)} {
        std::cout << "Moved a thing called " << name_ << " from " << &t << " to " << this << std::endl;
    }
    Thing(const Thing& t) : name_{t.name_} {
        std::cout << "Copied a thing called " << name_ << " from " << &t << " to " << this << std::endl;
    }

    ~Thing() {
        std::cout << "Deconstructed a thing called " << name_ << " at " << this << std::endl;
    };
    std::string name_;
};


int main() {
    std::vector<Thing> things{Thing("A")};
    std::cout << "Size: " << things.size() << " Capacity: " << things.capacity() << std::endl;
    things.emplace_back("B");
    std::cout << "Size: " << things.size() << " Capacity: " << things.capacity() << std::endl;
}

Example output:示例输出:

Constructed a thing called A at 0x1111
Copied a thing called A from 0x1111 to 0x2222
Deconstructed a thing called A at 0x1111
Size: 1 Capacity: 1
Constructed a thing called B at 0x3333
Moved a thing called A from 0x2222 to 0x4444
Deconstructed a thing called A at 0x2222
Size: 2 Capacity: 2
Deconstructed a thing called A at 0x4444
Deconstructed a thing called B at 0x3333

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM