std::emplace_back 调用向量中其他对象的构造函数?
Posted
技术标签:
【中文标题】std::emplace_back 调用向量中其他对象的构造函数?【英文标题】:std::emplace_back invoking constructor of other objects in vector? 【发布时间】:2020-03-07 16:35:16 【问题描述】:我真的对std::vector::emplace_back
感到困惑。我运行以下代码:
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> thingsThing("A");
std::cout << "Size: " << things.size() << std::endl;
things.emplace_back("B");
std::cout << "Size: " << things.size() << std::endl;
并得到这个输出:
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
到底为什么things.emplace_back("B")
会调用 A 的解构器?
【问题讨论】:
添加第二个元素是调用向量的调整大小,将旧元素复制到新向量,以及销毁旧元素。您的对象有一个默认的复制构造函数。创建一个具有类似 cout 的显式复制构造函数(和一个移动构造函数),您将看到正在复制或移动构造的新 A 对象。 请注意,C++ 术语是析构函数,而不是解构函数。 【参考方案1】:std::vector
将对象连续存储在分配的内存块中。当该块的大小变得太小而无法向其中添加新元素时,它必须分配一个新的更大的内存块并将向量中当前存在的元素复制/移动到该新分配中。之后,之前分配中的对象被销毁,涉及到析构函数调用。
您没有看到正在制作的副本,因为您没有定义自定义复制构造函数。如果你这样做了,你会看到A
的副本是在原始A
被破坏之前构造的副本。如果定义noexcept
移动构造函数,您将看到A
的副本在原始A
被破坏之前被移动构造。
【讨论】:
世界再次变得有意义。谢谢!【参考方案2】:发生的情况是,当您将 B
添加到向量时,该向量可能只有 1 个元素的容量,因此必须将其现有元素移动到另一个向量中(破坏原始存储中的那个)
让我们添加更多日志来看看会发生什么:
#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> thingsThing("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;
示例输出:
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
【讨论】:
以上是关于std::emplace_back 调用向量中其他对象的构造函数?的主要内容,如果未能解决你的问题,请参考以下文章