Обработка изменений типа с помощью auto в C++

Тип возвращаемого значения изменен с const Bar& getBar() на const Bar getBar().

Если я использую: const auto& bar = getBar();

и тип возвращаемого значения изменится. У меня есть ссылка на временный объект.

Если я использую: const auto bar = getBar();

я всегда делаю копию Bar.

Какова наилучшая практика для этой проблемы?

class Bar {
public:
    Bar() = default;
    Bar(const Bar&) = default;
    Bar(Bar&&) = delete;
    Bar& operator=(const Bar&) = delete;
    Bar& operator=(const Bar&&) = delete;

    void setValue(int i);
    int value() const;

private:
    int m_i = 0;
};

class Foo {
public:
    Foo(Bar& bar) : m_bar(bar) {}
    Foo(const Foo&) = delete;
    Foo(Foo&&) = delete;
    Foo& operator=(const Foo&) = delete;
    Foo& operator=(const Foo&&) = delete;

    const Bar& giveMeBar();

private:
    Bar& m_bar;
};

int main() {

    auto bar = std::make_unique<Bar>();
    auto foo = std::make_unique<Foo>(*bar.get());

    const auto& barFromFoo = foo->giveMeBar();
    bar->setValue(2);

    std::cout << "original bar: " << bar->value() << std::endl;
    std::cout << "bar from foo: " << barFromFoo.value() << std::endl;
}

Нет, у вас не будет ссылки на временный объект, как на объект, который немедленно уничтожается. Вы будете удивлены, узнав, что получите ссылку на «несколько» временный объект, который будет существовать до тех пор, пока не закончится его область действия. Что касается кодекса по своему охвату, то он будет таким же постоянным, как и сама земная твердь.

Sam Varshavchik 15.03.2024 16:27

В показанном коде нет getBar().

3CxEZiVlQ 15.03.2024 16:29

как вы думаете, почему auto актуален? const Bar& barFromFoo = foo->giveMeBar(); vs Bar barFromFoo = foo->giveMeBar(); точно такая же история

463035818_is_not_an_ai 15.03.2024 16:36
auto — это просто вывод типа. Это не утиная типизация, это строгая типизация (через выведенный тип). Вы хотели бы auto const& получить константную ссылку, или auto& получить ссылку, или auto&& получить ссылку-или-константную ссылку, в зависимости от ситуации. Или просто auto чтобы получить отдельный экземпляр. Или auto const чтобы получить отдельную копию, то есть const.
Eljay 15.03.2024 16:37

Какова наилучшая практика для решения этой проблемы? Мои коллеги, которые много знают об этом, говорят, что отдают предпочтение семантике значений. Возврат по значению. Передача по значению. Склонность в пользу API неизменяемых объектов, а не API изменяемых объектов.

Eljay 15.03.2024 16:42

Лучше всего узнать, нужен ли вам псевдоним, или скопировать и ввести auto& или auto в зависимости от этого. Другая лучшая практика — когда интерфейс того, что вы использовали, изменился, вы поддерживаете свой код в соответствии с изменениями.

Öö Tiib 15.03.2024 16:42

Я написал ответ, но на самом деле я не совсем уверен, что вы называете «проблемой». Как вы думаете, что-то не так с выводом текущих кодов? Или с выводом кода после изменения типа возвращаемого значения?

463035818_is_not_an_ai 15.03.2024 16:57

Несвязано, но const для возвращаемого типа по значению вряд ли будет полезен. Единственное, что он делает, это не позволяет писать что-то вроде getBar()->setValue(1). Если возвращаемое значение хранится в переменной, то const вообще не имеет значения, и имеет значение только const переменной.

user17732522 15.03.2024 16:59
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать 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
8
81
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

То, что на самом деле является «лучшей практикой», основано на мнениях. Я лишь попытаюсь объяснить, почему ваша предпосылка неверна, чтобы вы могли сами составить свое мнение о том, что является хорошей практикой, и/или оценить некоторые рекомендации по этому вопросу.

Если я использую: const auto& bar = getBar(); и тип возвращаемого значения изменится. У меня есть ссылка на временный объект.

Время жизни временного объекта продлевается и привязывается к постоянной ссылке. Нет проблем. Если вы хотите избежать ненужного копирования, не делайте копии. В показанном коде вы можете без проблем заменить const Bar& giveMeBar(); на const Bar giveMeBar();.

Для иллюстрации рассмотрим этот пример:

#include <iostream>


struct foo {
    ~foo(){ std::cout << "yes. I leave now. Bye\n";}
};

foo bar() { return foo{};}

int main() {
    const foo& f = bar();
    std::cout << "are you still there?\n";    
}

Вывод :

are you still there?
yes. I leave now. Bye

PS: auto в этом ничего не меняет. Следующие выражения попарно эквивалентны:

const auto& barFromFoo = foo->giveMeBar();   
const Bar& barFromFoo = foo->giveMeBar();   // same

// and
const auto barFromFoo = foo->giveMeBar();
const Bar barFromFoo = foo->giveMeBar();   // same

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