gpt4 book ai didi

c++ - 如何最好地将 emplace 与 std::map 一起使用

转载 作者:搜寻专家 更新时间:2023-10-31 02:01:53 24 4
gpt4 key购买 nike

我正在尝试使用 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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com