Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/134.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ can';我是否将map[]运算符与const function关键字一起使用?_C++_Constants - Fatal编程技术网

C++ can';我是否将map[]运算符与const function关键字一起使用?

C++ can';我是否将map[]运算符与const function关键字一起使用?,c++,constants,C++,Constants,我得到了这个函数: bool Table::FindCard(const int& i, const Card& card) const{ std::vector<Card>::const_iterator iter = table[i].begin(); for(; iter != table[i].end() ; ++iter){ if(*iter == card){ return true; } } retur

我得到了这个函数:

bool Table::FindCard(const int& i, const Card& card) const{
  std::vector<Card>::const_iterator iter = table[i].begin();
  for(; iter != table[i].end() ; ++iter){ 
    if(*iter == card){
        return true;
    }
  }

  return false;
}
#include <map>
#include <string>
#include <utility>
#include <type_traits>
#include <iostream>
#include <boost/optional.hpp>


template<class Map>
auto maybe_get_impl(Map& map, typename Map::key_type const& key)
{
    using reference_type = std::conditional_t<
    std::is_const<std::remove_reference_t<Map>>::value,
    typename Map::mapped_type const&,
    typename Map::mapped_type&>;
    boost::optional<reference_type> result;
    auto ifind = map.find(key);
    if (ifind != map.end())
    {
        result = ifind->second;
    }
    return result;
}

template<class K, class V, class Comp, class A>
auto maybe_get(std::map<K, V, Comp, A> const& map, K const& key)
{
    return maybe_get_impl(map, key);
}

template<class K, class V, class Comp, class A>
auto maybe_get(std::map<K, V, Comp, A>& map, K const& key)
{
    return maybe_get_impl(map, key);
}

int main()
{
    std::map<int, std::string> mymap;
    mymap.emplace(1, "hello");
    mymap.emplace(2, "world");

    // note: non-const because we're taking a reference from a mutable map;
    std::string part = std::string("goodbye, cruel world");

    std::cout << maybe_get(mymap, 1).value_or(part) << std::endl;
    std::cout << maybe_get(mymap, 2).value_or(part) << std::endl;
    std::cout << maybe_get(mymap, 0).value_or(part) << std::endl;
}
一切顺利

原因是运算符[]不是常量?我知道一个常量函数只能调用其他常量函数

谢谢

原因是运算符[]不是常量?我知道一个常量函数只能调用其他常量函数

对,<如果键不存在,则指定code>运算符[]来创建新的默认构造元素,这在
const
映射上是不合理的,因此它没有标记为
const


当然,您可以指定
const
版本来抛出异常(正如
at
所做的那样),或者-我不知道-如果找不到键,则调用
终止
,但遗憾的是标准没有这样说。您必须使用
at
或(ugh)
查找

对于
std::map
操作符[]
将返回与给定键关联的值的引用。如果该键不存在,将插入该键。由于这明显改变了映射,因此此函数不是
const
,不能针对
const
对象调用。

运算符[]将在键尚不存在的情况下向映射中插入元素。这不是一个常量操作。
使用map.at()保持常量。

如前所述:
操作符[]
无cont
成员,可以替换为
at

我只想在前面的答案中添加可编译代码,以便为您提供一个直观的示例

bool Table::FindCard(const int& i, const Card& card) const{
  std::vector<Card>::const_iterator iter = table.at(i).begin();
  for(; iter != table.at(i).end() ; ++iter){ 
    if(*iter == card){
        return true;
    }
  }

  return false;
}
bool表::FindCard(const int&i,const Card&Card)const{
std::vector::const_迭代器iter=table.at(i).begin();
对于(;iter!=表.at(i).end();++iter){
if(*iter==卡){
返回true;
}
}
返回false;
}

在这个问题的根源上有一个哲学问题,就像所有C++库的决定一样。

向量
中,为常量和非常量情况定义了
运算符[]
。这是合理的,因为对于长度为N的向量,
运算符[](0…N-1)
将始终具有意义,无论是否为常量。元素将存在

以此为基准,地图应该做什么?没有绝对标准来确定是否存在任何下标(键)

使用可变
操作符[]
,选择默认构造元素是合理的-在调用方引用它之后,他希望它存在,我们可以使它存在。这是一条最不令人惊讶的道路

那么不可变的情况呢?元素可能存在,也可能不存在,如果不存在,我们就不能对映射进行变异,因为这将违反
const
的精神

我们也不应该抛出异常,因为对于习惯于处理
vector
的人来说,这可能会让他们感到惊讶,因为在这里,不期望(或可能)出现异常。然后,我们将有两个外观相似、行为非常不同的接口

答案是根本不提供可变运算符[]。开发人员(像您一样)可能会惊讶地发现它并不存在,但他们有机会查看文档并意识到他们找错了方向

如前所述,我们有
at()
(如果下标不存在,则抛出异常,如向量),我们有
find()

在boost(很快,c++17)的帮助下,我们可以为自己提供一个实用函数:

bool Table::FindCard(const int& i, const Card& card) const{
  std::vector<Card>::const_iterator iter = table[i].begin();
  for(; iter != table[i].end() ; ++iter){ 
    if(*iter == card){
        return true;
    }
  }

  return false;
}
#include <map>
#include <string>
#include <utility>
#include <type_traits>
#include <iostream>
#include <boost/optional.hpp>


template<class Map>
auto maybe_get_impl(Map& map, typename Map::key_type const& key)
{
    using reference_type = std::conditional_t<
    std::is_const<std::remove_reference_t<Map>>::value,
    typename Map::mapped_type const&,
    typename Map::mapped_type&>;
    boost::optional<reference_type> result;
    auto ifind = map.find(key);
    if (ifind != map.end())
    {
        result = ifind->second;
    }
    return result;
}

template<class K, class V, class Comp, class A>
auto maybe_get(std::map<K, V, Comp, A> const& map, K const& key)
{
    return maybe_get_impl(map, key);
}

template<class K, class V, class Comp, class A>
auto maybe_get(std::map<K, V, Comp, A>& map, K const& key)
{
    return maybe_get_impl(map, key);
}

int main()
{
    std::map<int, std::string> mymap;
    mymap.emplace(1, "hello");
    mymap.emplace(2, "world");

    // note: non-const because we're taking a reference from a mutable map;
    std::string part = std::string("goodbye, cruel world");

    std::cout << maybe_get(mymap, 1).value_or(part) << std::endl;
    std::cout << maybe_get(mymap, 2).value_or(part) << std::endl;
    std::cout << maybe_get(mymap, 0).value_or(part) << std::endl;
}
您是否尝试过
cbegin()
?“原因是运算符[]不是常量?”是的,请参阅。
#include <map>
#include <string>
#include <utility>
#include <type_traits>
#include <iostream>
#include <boost/optional.hpp>


template<class Map>
auto maybe_get_impl(Map& map, typename Map::key_type const& key)
{
    using reference_type = std::conditional_t<
    std::is_const<std::remove_reference_t<Map>>::value,
    typename Map::mapped_type const&,
    typename Map::mapped_type&>;
    boost::optional<reference_type> result;
    auto ifind = map.find(key);
    if (ifind != map.end())
    {
        result = ifind->second;
    }
    return result;
}

template<class K, class V, class Comp, class A>
auto maybe_get(std::map<K, V, Comp, A> const& map, K const& key)
{
    return maybe_get_impl(map, key);
}

template<class K, class V, class Comp, class A>
auto maybe_get(std::map<K, V, Comp, A>& map, K const& key)
{
    return maybe_get_impl(map, key);
}

int main()
{
    std::map<int, std::string> mymap;
    mymap.emplace(1, "hello");
    mymap.emplace(2, "world");

    // note: non-const because we're taking a reference from a mutable map;
    std::string part = std::string("goodbye, cruel world");

    std::cout << maybe_get(mymap, 1).value_or(part) << std::endl;
    std::cout << maybe_get(mymap, 2).value_or(part) << std::endl;
    std::cout << maybe_get(mymap, 0).value_or(part) << std::endl;
}
hello
world
goodbye, cruel world