c++ - 为什么将不存在的键应用于 map::find 会在 C++ 中返回具有第一个值映射大小的迭代器?

标签 c++ dictionary stl

我有一个类似下面代码片段的用例,在 getter 返回的映射中使用 map::find 来查找不存在的键实际上会找到一个迭代器,其第一个值是 map (可能),因此不会像预期的那样运行,等于 map::end

这可能是因为我的 map 是 getter 返回的 map 。并在不将其分配给变量的情况下使用了 map 。这样 getter 返回值可能已经被立即销毁了。

  1. 那么如果我的猜测是正确的呢?
  2. 为什么它返回 map 的大小而不是它的结束迭代器?

    #include <iostream>
    #include <map>


    class B {
        long long id_;

        public:
        B() = default;
        explicit B(long long);
        ~B() = default;
    };

    B::B(long long int id) : id_(id) {}


    class A {
        std::string id_;
        std::map<long long, std::shared_ptr<B>> b_;

        public:
        A() = default;
        explicit A(std::string id);
        ~A() = default;

        const std::string &id() const;

        std::map<long long, std::shared_ptr<B>> b();

    };

    A::A(std::string id): id_(id) {
        b_[1] = std::make_shared<B>(1);
        b_[2] = std::make_shared<B>(2);
    }

    const std::string &A::id() const {
        return id_;
    }

    std::map<long long, std::shared_ptr<B>> A::b() {
        return b_;
    }


    int main() {
        std::shared_ptr<A> a = std::make_shared<A>("arst");
        if (a->b().find(3) != a->b().end()) {
            std::cout << a->b().find(3)->first << std::endl;
            std::cout << a->b().at(3) << std::endl;
        }
    }

运行如下:

clang --version
Apple LLVM version 10.0.0 (clang-1000.10.44.4)
Target: x86_64-apple-darwin18.2.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

输出:

clang++ test.cc -std=c++11
./a.out
2
libc++abi.dylib: terminating with uncaught exception of type std::out_of_range: map::at:  key not found
[1]    64348 abort      ./a.out

最佳答案

std::map<long long, std::shared_ptr<B>> A::b();

您将按值返回 map,因此每次调用 a->b() 都会创建 map 的新拷贝 b_ 这就是为什么要进行这种比较:

a->b().find(3) != a->b().end()

...是未定义的行为,因为每次调用 b() 都会返回不同的映射和 comparing iterators from different container is undefined behavior .

更改您的声明(和定义)以返回一个 (const-)reference:

const std::map<long long, std::shared_ptr<B>>& A::b();

关于c++ - 为什么将不存在的键应用于 map::find 会在 C++ 中返回具有第一个值映射大小的迭代器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54128830/

相关文章:

c++ - 在 XCode 4.4.1 上构建 gtest 框架

C++ 确定是否在不定义预处理器符号的情况下使用调试符号进行编译

c# - 在镜像模式 Windows 7 中以编程方式更改屏幕方向

dictionary - Elixir:重命名字典中的键

c++ - 我可以/应该从 STL 迭代器继承吗?

c++ - 基于矩阵引起的排序对 vector 进行排序时出现段错误

c++ - 使用类成员函数对象推导成员函数返回类型

python - 如何在迭代字典时从字典中删除项目?

swift - 如何过滤字典数组

c++ - 新的 C++11 emplace 方法是否会使以前的 C++98/03 push_back/insert 方法过时?