C++ y要添加的新元素的值(尽管通常带有默认值)。在这种情况下,无法在现有元素和新元素之间的空间中指定元素的值

C++ y要添加的新元素的值(尽管通常带有默认值)。在这种情况下,无法在现有元素和新元素之间的空间中指定元素的值,c++,stdmap,design-rationale,C++,Stdmap,Design Rationale,地图的使用方式也有根本的区别。对于向量,通常在添加到向量的东西和使用向量中已有的东西之间有一个清晰的划分。有了映射,情况就不那么真实了——更常见的情况是看到代码操纵存在的项(如果有),或者添加新项(如果不存在)。操作符[]的设计反映了这一点。map.insert(键,项);确保键位于映射中,但不会覆盖现有值 map.operator[键]=项目;确保键位于映射中,并用项覆盖任何现有值 这两个操作都非常重要,足以保证只需要一行代码。设计者可能选择了对操作符[]更直观的操作,并为另一个创建了一个函数

地图的使用方式也有根本的区别。对于向量,通常在添加到向量的东西和使用向量中已有的东西之间有一个清晰的划分。有了映射,情况就不那么真实了——更常见的情况是看到代码操纵存在的项(如果有),或者添加新项(如果不存在)。操作符[]的设计反映了这一点。

map.insert(键,项);确保键位于映射中,但不会覆盖现有值

map.operator[键]=项目;确保键位于映射中,并用项覆盖任何现有值


这两个操作都非常重要,足以保证只需要一行代码。设计者可能选择了对操作符[]更直观的操作,并为另一个创建了一个函数调用。

考虑这样的输入-3个块,每个块2行,第一行是第二行中的元素数:

5
13 20 22 43 146
4
13 22 43 146
5
13 43 67 89 146
问题:计算所有三个块的第二行中存在的整数数。(对于该样本输入,只要所有三个块的第二行中有13、43和146,则输出应为3)

看看这个代码有多好:

int main ()
{
    int n, curr;
    map<unsigned, unsigned char> myMap;
    for (int i = 0; i < 3; ++i)
    {
        cin >> n;
        for (int j = 0; j < n; ++j)
        {
            cin >> curr;
            myMap[curr]++;
        }

    }

    unsigned count = 0;
    for (auto it = myMap.begin(); it != myMap.end(); ++it)
    {
        if (it->second == 3)
            ++count;
    }

    cout << count <<endl;
    return 0;
}
它插入了一个带有key
curr
的元素,并在映射中不存在key时将值初始化为零。而且它也增加了值,不管元素是否在映射中


看看有多简单?很好,不是吗?这是一个非常方便的示例。

不可能避免创建对象,因为操作符[]不知道如何使用它

myMap[“苹果”]=“绿色”

char const*cColor=myp[“苹果”]

我建议map容器应该添加如下函数

if(!myMap.exist(“苹果”))
抛出…

阅读比阅读更简单、更好

if(myMap.find(“苹果”)!=myMap.end()

抛出…

好的,
操作符[]
返回引用很方便。所以它应该插入一些东西,因为无法返回无效引用。为什么不创建一个引发异常的常量版本?因为异常是针对异常情况的。@sbi:除非您知道它存在?不过,是的,我刚刚意识到,如果它能像我想要的那样工作,那基本上就是一个发现,谢谢。尼克斯想得差不多。每当我使用映射进行查找时,我都必须检查find是否返回end,然后抛出异常,因为这是唯一合适的操作。如果这是主要原因,那么常量映射将返回无法分配给and
运算符[]的常量引用
对于常量贴图,不必创建值。但是对于常数映射,甚至没有一个
操作符[]
,你一定错了。我不知道这怎么会让我错。。。似乎如果常量映射上没有操作符[],这正好证明了我的观点。常量映射上没有
操作符[]
似乎表明
操作符[]
纯粹是为了修改映射。我一定是误解了你的意思。如果STL的设计者不认为任何类型的
操作符[]
对常量映射都有意义,那么他们显然在修改映射时看到了
操作符[]
的全部含义,就像答案中的赋值一样……拥有
操作符[]
有两种截然不同的语义,这取决于map是否为const
对我来说听起来是个坏主意。事实上,
[]
具有某些定义良好的语义,而
const
map根本不支持这些语义,因此它不存在。@EToreo&sth:我可以看出我的观点有点弱<代码>
让我。。。实际上,
operator[]
有两个用途:可以使用它访问现有元素,也可以插入元素。这两个函数都有专门的函数,所以可能是组合,为什么存在
操作符[]
。对于添加语义,您有
insert()
,对于访问语义,您有
find()
-除了
find()
可以返回“不存在的元素”,而操作符不能。使用
操作符[]
进行添加和查找时都需要插入语义。请参阅我的评论,了解我认为这是错误的原因。但是向量不也返回引用吗?这里有什么区别?抱歉,我不熟悉std::map的内部,所以从内部来看这可能是显而易见的。使用[]访问向量超出边界是未定义的行为。我猜map在这种情况下也可以调用一些未定义的行为,但您真的喜欢吗?对于向量,很容易发现索引是否有效,而对于映射,则很容易发现索引是否有效(您可以先调用find,在这种情况下,调用[]将毫无意义,因为您应该已经找到了要查找的项)。@n1ck:std::vector将返回无效引用(因为这样做很容易)。map没有一种简单的方法返回引用。传统上,maps的接口(在所有语言中,而不仅仅是C++)允许您编写类似于
map[key]=value,映射将替换现有值或根据需要插入新值。这是一个由来已久的惯例,因此
std::map
遵循它也就不足为奇了。但是,由于
operator[]
无法判断它必须返回的引用是否将用于
operator=
的左侧,因此它必须始终假设最坏的情况,并因此插入一个新元素。@N1ck:它们可能比std库旧<代码>:)
对于std::vector,运算符[]未选中。如果你试图
5
13 20 22 43 146
4
13 22 43 146
5
13 43 67 89 146
int main ()
{
    int n, curr;
    map<unsigned, unsigned char> myMap;
    for (int i = 0; i < 3; ++i)
    {
        cin >> n;
        for (int j = 0; j < n; ++j)
        {
            cin >> curr;
            myMap[curr]++;
        }

    }

    unsigned count = 0;
    for (auto it = myMap.begin(); it != myMap.end(); ++it)
    {
        if (it->second == 3)
            ++count;
    }

    cout << count <<endl;
    return 0;
}
myMap[curr]++;