- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在尝试使用 std::map::emplace()
而不是插入。我有一个简单的测试程序如下:
#include <iostream>
#include <map>
#include <string>
class CTest
{
public:
CTest() : Value(0), Name() { std::cout << "Default constructor" << std::endl; };
CTest(int val, const std::string &name) : Value(val), Name(name) {
std::cout << "Parameterized constructor" << std::endl; }
CTest(const CTest& test) {
Value = test.Value; Name = test.Name; std::cout << "Copy Constructor" << std::endl; }
CTest(CTest&& test) noexcept {
Value = test.Value; Name = test.Name; std::cout << "Move Constructor" << std::endl; }
CTest& operator=(const CTest& test) {
Value = test.Value; Name = test.Name; std::cout << "Copy assignment" << std::endl; return *this; }
CTest& operator=(CTest &&test) noexcept {
Value = test.Value; Name = test.Name; std::cout << "Move assignment" << std::endl; return *this; }
~CTest() { std::cout << "Destructor" << std::endl; }
private:
int Value;
std::string Name;
};
int main()
{
CTest t1(1, "hello");
CTest t2(2, "hello");
std::map<int, CTest> testMap;
testMap[1] = t1; //1
testMap.emplace(2, t2); //2
testMap.emplace(3, CTest(3, "hello")); //3
testMap.emplace(std::piecewise_construct, std::forward_as_tuple(4), std::forward_as_tuple(4, "hello")); //4
testMap.emplace(std::piecewise_construct, std::forward_as_tuple(4), std::forward_as_tuple(std::move(t1))); //5
return 0;
}
每一个的输出是:
1
默认构造函数
复制作业
2
复制构造函数
3
参数化构造函数
移动构造函数
析构函数
4
参数化构造函数
5
移动构造函数
析构函数
1涉及最多的复制:使用默认构造函数在映射中创建一个条目,然后进行复制赋值。我很惊讶地看到对 3 和 5 的析构函数调用。在这两种情况下,传递的值都是右值。那么传入的右值是不是创建了一个temporary,用完就删除了?这就引出了一个问题,使用 emplace 的正确方法是什么?是否应该像 4 那样只传递构造函数的参数?正如我的结果所示,这是性能最好的。
最佳答案
Should you just pass the arguments of the constructor
是的,因为这确实是所有 emplace()
函数的设计目的。使用 insert()
,您必须构建一个对象,然后 [通常] 将其复制到您的容器中。通常,如果您使用的是容器,那么您只是在构建,以便可以将它们放入容器中。正如您在测试中看到的那样,这是一些额外的工作。
emplace()
旨在让您直接在容器中构建。您可以通过向 emplace 函数提供构造函数参数来实现。 insert()
如果您已经有了一个对象并想将其放入容器中,则使用该方法。
我有一个尖刻的评论,其他人注意到值得多解释一下。如果您的类(我称之为 Foo
)具有单参数构造函数,看起来您可以通过传递单个参数来完成与 emplace()
相同的事情到类似 insert()
或 push_back()
或 any 将 Foo 作为参数的地方。这是语言的一个“特性”,编译器会隐式地为您构造一个 Foo
并使用它。问题是在引擎盖下,它并没有做同样的事情。 emplace()
将直接在容器中构建您的对象,通过利用单个参数构造函数来伪造它仍然会导致创建拷贝。另一个需要考虑的缺点是这种隐式转换。它会损害代码的可读性,或者更糟的是,破坏东西。这可以通过将构造函数标记为 explicit
来避免。
关于c++ - 如何最好地将 emplace 与 std::map 一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58288312/
我有一个 std::unordered_map,它的 value_type 没有默认构造函数,所以我不能执行以下操作 auto k = get_key(); auto& v = my_map[k];
我有这个代码: std::vector> vec; vec.emplace_back("a", 1); //success vec.emplace(vec.end(), "b", 2); //comp
两种放置方式: std::unordered_map m; 首先:放置移动的键和值 // 1. { std::string k1 = "key1"; std::string v1 =
我正在实现一个简单的圆形 vector 类。我想实现一个 emplace 成员函数,但出现了一个我不明白的错误。对于我做错的事情,这可能是一个简单的修复,但由于我对可变参数模板没有太多经验,我无法弄清
以下代码使用 gcc 6.3 ( https://godbolt.org/g/sVZ8OH ) 编译时没有任何错误/警告,但由于下面标记的无效内存访问,它包含危险的未定义行为。根本原因是在 empla
如果我有这张 map std::unordered_map sockets; //a map holding all active sockets 我怎么可以这样做: sockets[_myId]=
我将这个容器作为类中的一个成员: std::unordered_map m_fruits; 我想在同一个类中向它添加一个新元素,我尝试了两种方法,两种方法都应该基于示例工作。 (在 emplace 的
需要为整数和一些用户定义的类创建 unordered_map - MyClass,其中 MyClass 使用互斥锁进行数据访问同步,即 MyClass 对象不能被复制或移动。是否可以创建这样的 map
#include #include #include using namespace std; struct Time { int h; int m; int s; };
我在myclass.h 文件中有以下代码: typedef std::unordered_set Parameters; class MyClass { public: voi
我正在尝试使用 emplace()就地 build 一个map条目(使用 boost )。关键对象构造函数 arg 通过模板魔术正确转发,但是 V object constructor arg 变为
下面的代码给出了段错误,有人能赐教吗?我想要实现的是让优先级队列按 tv.t 的升序或 tv.m 的降序排序。 struct tv { int m; int c; int t;
如果我创建一个带有 explicit 的结构构造函数 struct A { int x; explicit A(int x):x(x){}; }; 然后将其用作 mapped_type
这个问题在这里已经有了答案: Why doesn't emplace_back() use uniform initialization? (1 个回答) 关闭 4 年前。 自 C++11 以来我们
我正试图提出一些论据来进行对象的就地构造。我不太明白在关联容器中使用 emplace 背后的基本原理,或者我可能只是以错误的方式使用/思考。如果有人可以共享代码片段以供使用,那就太好了。 像 map
假设我有一个 map : std::map map; map.emplace(1, 2); map.insert({3, 4}); 这两个调用会有什么区别吗? 在第一次调用中,这两个整数将按值复制到e
是std::map::emplace的点创建以某种方式在标准中指定的对象(即调用构造函数)?如果是,它是在检查此类 key 的存在之前发生的还是之后发生的? 在以下情况下很重要: struct X {
我有一组对象,我想使用 emplace 将对象添加到集合中。如果集合中不存在等效对象,则 set::emplace 创建一个对象并将其放入集合中。如果集合已经有一个等效对象,set::emplace
我有一个函数在标准无序映射容器上调用 emplace() 方法,我需要返回 emplace() 给出的准确返回值称呼。我知道它返回一个 std::pair 的迭代器(无论是新的还是旧的取决于成功的操作
我看到很多代码在工作中人们使用 emplace 和 emplace_back 和一个临时对象,像这样: struct A { A::A(int, int); }; vector v; vect
我是一名优秀的程序员,十分优秀!