map<string, pair<string, foo*>> 和 map<string, pair<string, foo&>> 有什么区别?

What is the difference between map<string, pair<string, foo*>> and map<string, pair<string, foo&>>?

我写一个摘要classfoobarclass继承自foo.

我想创建一个map<string, pair<string, foo&>>的地图容器,但我无法编译成功。编译器告诉我

“std::pair<std::string,foo &>::pair”: not appropriate default constructor

代码如下:

#include <iostream>
#include <string>
#include <windows.h>
#include <map>
#include <utility>

using namespace std;

class foo
{
public:
    virtual void t() = 0;
};

class bar :public foo
{
public:
    void t()
    {
        cout << "bar" << endl;
    }
};

int main()
{
    bar b;
    //wrong
    //map<string, pair<string, foo&>> t;
    //pair<string, foo&> p("b", b);
    //t["t"] = p;

    //right
    map<string, pair<string, foo*>> t;
    pair<string, foo*> p("b", &b);
    t["t"] = p;
    p.second->t();
}

我想知道map<string, pair<string, foo*>>map<string, pair<string, foo&>>的区别。

第一个示例(您标记为 "wrong")的问题是行 t[" t"] = p;。如果您查看 std::map::operator[] 的文档,您会发现以下段落:

  • value_type must be EmplaceConstructible from std::piecewise_construct, std::forward_as_tuple(key), std::tuple<>().

这意味着您的 mapped_type(在这种情况下,foo&)必须是默认可构建的。但是,引用必须始终 引用现有对象,不能默认构造它们。使用指针的示例很好,因为指针没有该限制。

您可以使用引用作为 mapped_type,但您必须避免使用 operator[]。例如,您可以找到带有 std::map::find or insert one with std::map::emplace 的元素。以下示例可以正常编译:

#include <string>
#include <map>
#include <utility>

using namespace std;

struct foo {};

int main()
{
    foo b;
    //wrong
    map<string, pair<string, foo&>> t;
    pair<string, foo&> p("b", b);
    t.emplace("t", p);
}