微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c ++:具有一对string_viewes的无序映射

如何解决c ++:具有一对string_viewes的无序映射

这是我的代码片段:

    struct PairHasher {
        size_t operator()(const std::pair<std::string_view,std::string_view>& stop_stop) const {
            return hasher(stop_stop.first) + 37*hasher(stop_stop.second);
        }
        std::hash<std::string_view> hasher;
    };


BOOST_FIXTURE_TEST_CASE(unordered_map_string_view_pair_must_be_ok,TestCaseStartStopMessager)
{
    const std::vector<std::string> from_stops = {"from_0","from_1","from_2"};
    const std::vector<std::string> to_stops = {"to_0","to_1","to_2"};

    std::unordered_map<std::pair<std::string_view,std::string_view>,std::int32_t,TransportCatalogue::PairHasher> distance_between_stops;
    for ( std::size_t idx = 0; idx < from_stops.size(); ++idx) {
        std::cout << from_stops[idx] << " : " << to_stops[idx] << std::endl;
        distance_between_stops[std::pair(from_stops[idx],to_stops[idx])] = idx;
    }

    std::cout << "MAP CONTENT :" << std::endl;
    for (auto const& x : distance_between_stops)
    {
        std::cout << x.first.first << " : " << x.first.second << std::endl;
    }
}

我希望在容器内看到 3 对,但输出中只有 1 对:

MAP CONTENT :
from_2 : to_2

那么,哪里又丢了两对?我做错了什么?

解决方法

将我的评论移至答案。

这太狡猾了。我注意到在 Compiler Explorer 中发生了变化:

distance_between_stops[std::pair(from_stops[idx],to_stops[idx])] = idx;

distance_between_stops[std::pair(std::string_view{from_stops[idx]},std::string_view{to_stops[idx]})] = idx;

修复了错误。这暗示问题在于某些隐式 string -> string_view 转换。确实如此,但它隐藏在额外的一层之后。

std::pair(from_stops[idx],to_stops[idx]) 创建一个 std::pair<std::string,std::string>,但 distance_between_stops 需要一个 std::pair<std::string_view,std::string_view>。当我们向映射中插入值时,这种转换会通过重载 #5 here:

隐式发生
template <class U1,class U2>
constexpr pair(pair<U1,U2>&& p);
  1. first 初始化 std::forward<U1>(p.first),用 std::forward<U2>(p.second) 初始化第二个。
  • 当且仅当 std::is_constructible_v<first_type,U1&&>std::is_constructible_v<second_type,U2&&> 都是 true 时,此构造函数参与重载决议。
  • 此构造函数为 explicit 当且仅当 std::is_convertible_v<U1&&,first_type>falsestd::is_convertible_v<U2&&,second_type>false

(作为参考,std::is_constructible_v<std::string_view,std::string&&>std::is_convertible_v<std::string&&,std::string_view> 都是 true,所以我们知道这个重载是可行且隐含的。)

看到问题了吗?当我们使用映射的 operator[] 时,它必须进行隐式转换以创建具有正确类型的键。这种隐式转换构造了一对 string_view,它们从本地 string 对查看 临时 内存,而不是 vector 中的底层字符串。换句话说,它在概念上类似于:

std::string_view foo(const std::string& s) {
    std::string temp = s + " foo";
    return temp;
}
int main() {
    std::string_view sv = foo("hello");
    std::cout << sv << "\n";
}

Clang 为这个小例子发出警告,但没有 OP 的完整例子,这很不幸:

warning: address of stack memory associated with local variable 'temp' returned [-Wreturn-stack-address]
    return temp;
           ^~~~

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?