提问人:Milad Rasouli 提问时间:8/16/2022 最后编辑:Milad Rasouli 更新时间:8/16/2022 访问量:68
如何在向量中构造一些类?
How to construct some classes in a vector?
问:
我正在处理一个类,我需要有类的向量。我希望将对象构建到位,而不是使用复制构建。似乎使用复制结构是不可避免的。
#include <iostream>
#include <string>
#include <vector>
class MyData {
public:
int age;
std::string name;
MyData(int age, std::string name) : age(age), name(name)
{
std::cout << "MyData::MyData(int, std::string)\n";
}
MyData(const MyData& myData) : age(myData.age), name(myData.name)
{
std::cout << "MyData::MyData(const MyData&)\n";
}
MyData(MyData&& myData)
:age(std::move(myData.age)), name(std::move(myData.name))
{
std::cout << "MyData::MyData(MyData&&)\n";
}
~MyData() {
std::cout << "MyData::~MyData()\n";
}
};
#define DEBUG(...) std::cout << "Exec: " #__VA_ARGS__ << ";\n"; __VA_ARGS__
int main()
{
DEBUG(std::vector<MyData> sb1);
DEBUG(sb1.emplace_back(MyData{ 32, "SJ" }));
DEBUG(sb1.emplace_back(MyData{ 42, "SJ" }));
}
代码输出如下:
Exec: std::vector<MyData> sb1;
Exec: sb1.emplace_back(MyData{ 32, "SJ" });
MyData::MyData(int, std::string)
MyData::MyData(MyData&&)
MyData::~MyData()
Exec: sb1.emplace_back(MyData{ 42, "SJ" });
MyData::MyData(int, std::string)
MyData::MyData(MyData&&)
MyData::MyData(const MyData&)
MyData::~MyData()
MyData::~MyData()
MyData::~MyData()
MyData::~MyData()
C:\Users\XOXOX\source\repos\cpp_stack\x64\Debug\cpp_stack.exe (process 12832) exited with code 0.
Press any key to close this window . . .
我正在使用 C++ 2020 和 MSVC。
答:
2赞
463035818_is_not_an_ai
8/16/2022
#1
你误解了什么。emplace_back
它接受您传递的参数,并将它们转发给相应的构造函数。
如果你这样做
sb1.emplace_back(MyData{ 32, "SJ" });
然后调用移动(或复制)构造函数。 不能神奇地撤消临时的创造。如果要就地创建元素,请不要传递临时的:emplace_back
MyData
sb1.emplace_back(32, "SJ" );
这将使用 and 参数调用构造函数。int
std::string
评论
0赞
Milad Rasouli
8/16/2022
谢谢。它变得更好了。但它在调用 copy constructor 后仍然调用析构函数。这不是我需要的。我想在向量中构造类,而不会产生进一步的开销。我目前的结果是:''' Exec: std::vector<MyData> sb1;执行: sb1.emplace_back(32, “SJ” );MyData::MyData(int, std::string) exec: sb1.emplace_back(42, “SJ” );MyData::MyData(int, std::string) MyData::MyData(const MyData&) MyData::~MyData() MyData::~MyData() MyData::~MyData()'''
0赞
Sneftel
8/16/2022
@MiladRasouli 事实并非如此。至少,该代码没有。如果导致复制构造函数在刚刚构造的元素上调用(而不是在调整大小时调用以前的元素),那么您应该问一个新问题,因为这不是 C++ 所做的。emplace_back(your, args)
0赞
463035818_is_not_an_ai
8/16/2022
@MiladRasouli为什么它不是你需要的?被销毁的附加副本和元素来自矢量调整大小。您可以通过预先请求足够的容量来避免它,但不能通过单独在呼叫中执行某些操作来避免它emplace
0赞
Milad Rasouli
8/16/2022
我最近遇到了一个例子,和 .在示例中,这些用于地图。有趣的是,地图在 之后不会破坏类。现在我想做同样的事情,但为了std::piecewise_construct
std::forward_as_tuple
emplace
vector
1赞
463035818_is_not_an_ai
8/16/2022
@MiladRsouli这样做是一样的,只是向量在增加其容量时需要重新分配,地图没有容量。施工后尝试,重新分配将消失sb1.reserve(2)
6赞
Goswin von Brederlow
8/16/2022
#2
首先,当你写的时候
DEBUG(sb1.emplace_back(MyData{ 32, "SJ" }));
创建一个传递给函数的临时对象。关键是它调用了 costructor in-place。因此,您必须为它提供创建对象的参数,而不是临时对象,否则它必须使用复制/移动构造函数。emplaced_back
emplace_back
第二个是容量为 0 的向量。因此,向其添加项目将不得不调整大小,这意味着复制,因为移动构造函数不是 . 无法在调整大小期间处理异常,因此它不会冒险使用移动构造函数。sb1
noexcept
std::vector
您应该保留右侧以避免调整大小。
评论
0赞
Milad Rasouli
8/16/2022
谢谢。@463035818_is_not_a_number我之前需要打电话sb.reserve(2)
emplace(...)
1赞
463035818_is_not_an_ai
8/16/2022
吹毛求疵:保留并不能避免调整大小。它避免了由于在向量调整大小时增加容量而重新分配。
0赞
Goswin von Brederlow
8/16/2022
我说的是支持向量的内存大小调整。不变。std::vector::size()
上一个:C++ 向量按值删除会发出错误
下一个:指向迭代器的 C++ 指针
评论
sb1.emplace_back(32, "SJ")
.您的版本等效于 。push_back