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

时间:2019-01-10 12:33:26

标签: c++ dictionary stl

我有一个类似下面的代码片段的用例,在获取返回的映射中使用map::find来查找不存在的键实际上会找到一个迭代器,其第一个值是映射的大小(可能),因此不会表现出预期的效果,等于map::end

这可能是因为我的地图是吸气剂返回的地图。并消耗了地图,而没有将其分配给变量。这样,getter返回的值可能会立即被破坏。

  1. 那么,如果我的猜测是正确的?
  2. 为什么它返回地图的大小而不是其最终迭代器?

    #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

2 个答案:

答案 0 :(得分:11)

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

您将按值返回map,因此每次调用a->b()时,都会创建地图b_的新副本,这就是这种比较的原因:

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

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

更改声明(和定义)以返回(const-)引用:

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

答案 1 :(得分:9)

您的函数A::b()通过值返回映射 。这意味着将返回一个 copy ,每次调用该 unique 副本,并且其迭代器与任何其他副本的迭代器不兼容

通过引用返回