Продление срока службы элемента временного контейнера

Применяется ли продление времени жизни временного объекта с помощью ссылок const к элементам временных контейнеров, как, например, в случае ссылки r в программе ниже?
Гарантируется ли это стандартом C++?
Я читал, что такое продление срока службы применяется к подобъектам полных объектов, но могут ли элементы стандартных контейнеров квалифицироваться как подобъекты соответствующего контейнера?

#include <unordered_map>
#include <string>
#include <iostream>

using my_map = std::unordered_map<std::string, int>;

my_map func() {
    return my_map{{"foo", 42}};
}

int main() {
    const auto& r = func()["foo"];
    std::cout << "r = " << r << std::endl; // Is r valid here?
    return 0;
}

В данном конкретном примере это старая добрая висячая ссылка godbolt.org/z/j7vvhdoTf «предупреждение: объект, поддерживающий указатель, будет уничтожен в конце полного выражения [-Wdangling-gsl]»

Cory Kramer 29.07.2024 20:15

Между объектом и ссылкой, возвращаемой методом этого объекта, априори нет пожизненной связи. Представьте себе int global_int; struct my_map { int& operator[](std::string) { return global_int; } }. Возвращаемое значение operator[] — это ссылка на глобальный объект, время жизни которого не привязано к времени жизни my_map.

Raymond Chen 29.07.2024 20:24

Временное значение, возвращаемое функцией, привязано к неявному параметру this, и время жизни временного значения не продлевается.

3CxEZiVlQ 29.07.2024 20:25
Предупреждения вашего компилятора должны дать вам ответ на этот вопрос.
Drew Dormann 29.07.2024 20:26

@CoryKramer, к сожалению, я застрял на gcc 9.5, который, похоже, не выдает никаких предупреждений об этом с помощью -Wall -Wextra. Однако большое спасибо за указание на Godbolt, чтобы я мог опробовать такие выражения на каком-нибудь минимальном примере и оценить их правильность!

christosc 30.07.2024 08:47

@DrewDormann, к сожалению, я использую gcc 9.5, который не выдает таких предупреждений... В любом случае большое спасибо!

christosc 30.07.2024 08:48
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
6
55
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Нет, r недействителен. r становится недействительной ссылкой на временную ссылку, как только оператор r = func()["foo"]; завершается.

Вот доказательство концепции, основанное на вашем примере кода:

#include <unordered_map>
#include <string>
#include <iostream>


class Foo {
public:
    int value;

    Foo() : value(0) {
        value = 0;
    }
    Foo(int n) : value(n) {
    }
    ~Foo() {
        std::cout << "~Foo(" << value << ")\n";
    }
};

using my_map = std::unordered_map<std::string, Foo>;

my_map func() {
    return my_map{ {"foo", 42} };
}

int main() {
    const auto& r = func()["foo"];
    std::cout << "r.value = " << r.value << std::endl; // Is r valid here?
}

Когда я запускаю следующую программу, я получаю такие результаты:

~Foo(42)
~Foo(42)
r.value = -572662307    # GARBAGE OUTPUT

-572662307 — это 0xdddddddd в шестнадцатеричном формате, который отладка Visual Studio присваивает удаленной памяти, которая не была освобождена. Так что это явный признак того, что r определенно недействителен.

Это будет допустимо в вашем коде и выведет ожидаемое значение 42:

std::cout << "func['foo'] = " << func()["foo"] << std::endl; 

В конце вы наверняка имели в виду func()["foo"], а не func["foo"].

Eugene 29.07.2024 20:29

@Юджин, хороший улов. Зафиксированный.

selbie 29.07.2024 22:48

Другие вопросы по теме

Как мне обслуживать приложение React.js Vite, размещенное в экземпляре контейнера Azure, по настраиваемому маршруту, где маршрутизацией управляет Caddy?
Вариант контейнера модели публикации веб-приложения Azure не работает с Terraform
Невозможно получить доступ к контейнеру через локальный хост или IP-адрес хоста, несмотря на правильную привязку, но можно получить доступ к контейнеру через частный IP-адрес
Ошибка «МАНИФЕСТ НЕИЗВЕСТНО» при публикации стандартного веб-приложения ASP.NET Core в приложениях-контейнерах Azure
Почему по умолчанию для сборки контейнеров Windows внутри VS2022 используется компиляция вне контейнера?
Как установить недостающие модули Python в образ без дистрибутива?
Проблема с шириной контейнера CSS, не очень хорошо работает с «переполнением»?
Dpkg-checkbuilddeps: ошибка: неудовлетворенные зависимости сборки
Apache и PHP в отдельных контейнерах в Ubuntu
Образ Ubuntu Docker, эквивалентный vmImage: ubuntu