Почему мой const ref становится недействительным в этом коде и как этого избежать? Я не могу скопировать, это узкое место в моем приложении.
class Foo {
public:
const std::string& string() const {
return string;
}
private:
std::string string = "asdf";
};
Foo foo;
std::vector<std::pair<const std::string&, int>> invalid;
for (int i = 0; i < 5; i++) {
invalid.emplace_back(std::make_pair(foo.string(), i);
// after this line invalid[i].first is invalid
}
Игорь Тандетник уже указал на проблему в вашем коде. FWIW, я не думаю, что это хорошая идея, чтобы контейнеры ссылались на элементы других объектов по ссылке в любом случае — есть неявная зависимость от относительного времени жизни объектов. Вы можете рассмотреть возможность использования shared_ptr
в const string
, как в следующем:
#include <string>
#include <memory>
#include <vector>
class Foo {
public:
const std::shared_ptr<const std::string> string() const {
return _string;
}
private:
std::shared_ptr<std::string> _string = std::make_shared<std::string>("asdf");
};
int main()
{
Foo foo;
std::vector<std::pair<std::shared_ptr<const std::string>, int>> invalid;
for (int i = 0; i < 5; i++) {
invalid.emplace_back(std::make_pair(foo.string(), i));
}
}
make_pair
возвращает pair<std::string,int>
не pair<const std::string&, int>
потому что стандарт требует, чтобы это было так.
template <class T1, class T2>
constexpr pair<V1, V2> make_pair(T1&& x, T2&& y);
§ 20.3.3 — 8
Возвращает:
pair<V1, V2>(std::forward<T1>(x), std::forward<T2>(y));
где
V1
а такжеV2
определяются следующим образом: пусть Ui будетdecay_t<Ti>
за каждый ти. Тогда каждый Vi есть X&
если UI равенreference_wrapper
иначе Vi — это Ui.
Это должно работать в соответствии со стандартом:
invalid.emplace_back(std::make_pair(std::ref(foo.string()), i));
и это по мне
invalid.emplace_back(decltype(invalid)::value_type(foo.string(), i));