Почему применение несуществующего ключа к map :: find вернет итератор с размером карты первого значения в C ++? - PullRequest
0 голосов
/ 10 января 2019

У меня есть сценарий использования, подобный приведенному ниже фрагменту кода, использование map::find в карте, возвращаемой геттером, чтобы найти несуществующий ключ, фактически нашло бы итератор, первое значение которого является размером карты (вероятно), поэтому не ведет себя, как ожидалось, равно map::end

это, вероятно, из-за того, что моя карта была получателем возвращенной карты. И потреблял карту, не назначая ее переменной. Чтобы возвращаемое значение получателя могло быть немедленно уничтожено.

  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 голосов
/ 10 января 2019
std::map<long long, std::shared_ptr<B>> A::b();

Вы возвращаете map по значению, поэтому каждый раз, когда вы звоните a->b(), вы создаете новую копию карты b_, поэтому используется такой тип сравнения:

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

... is неопределенное поведение , поскольку каждый вызов b() возвращает другую карту, а сравнение итераторов из другого контейнера - неопределенное поведение .

Измените ваше объявление (и определение), чтобы оно возвращало (const -) ссылку:

const std::map<long long, std::shared_ptr<B>>& A::b();
0 голосов
/ 10 января 2019

Ваша функция A::b() возвращает карту по значению . Это означает, что возвращается копия , уникальная копия при каждом вызове и чьи итераторы не совместимы с итераторами из любой другой копии.

Возврат по ссылке .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...