Константные локальные переменные

На следующий код clang-tidy выдаёт

constness of str prevents automatic move

#include <string>

std::string foo() {
    const auto str = std::string{"42"};

    return str;
}

int main() {
    const auto str = foo();
}

Правда ли, что в таком случае надо все локальные переменные объявлять неконстантными? Или только классы с move конструкторами? А как же правило использовать const как можно чаще?

Однако конструктор копирования и перемещения явно не вызываются:

#include <iostream>

struct A {
    A() = default;

    A(const A&) {
        std::cout << "&\n";
    }

    A(A&&) noexcept {
        std::cout << "&&\n";
    }

    int x = 42;
};

auto foo() {
    const auto a = A{};

    return a;
}


int main() {
    const auto a = foo();

    std::cout << a.x << '\n';
}

Похожий вопрос https://stackoverflow.com/q/16089730.


Ответы (2 шт):

Автор решения: AR Hovsepyan

Думаю, как мне, так и всем, понятно, что вашу функцию можно заменить на:

A foo() { return A{}; }

Но и в этом случаи функция ничего не делает, и вместо нее можно просто использовать объект А, то есть ваш код:

const auto a = foo();
std::cout << a.x << '\n';

можно не задумываясь заменить на:

const A a = A{};
std::cout << a.x << '\n';

Современные компиляторы не хуже нас соображают, они все это делают, но перед этим еще могут предупреждать вас о том, что в вашем коде есть лишние попытки сделать код хуже.

В добавок ко всему этому в стандарт С++17 введено :

Обязательное избавление от копирования Изменён смысл понятия prvalue: теперь это всего лишь инициализация.

Это значит, что В коде A a = A{}; хоть всё ещё требуется и конструктор, и конструктор копирования, гарантированно будет вызван только конструктор. А значит будет выполнено:

const A a{};
std::cout << a.x << '\n';

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

→ Ссылка
Автор решения: HolyBlackCat

Правда ли, что в таком случае надо все локальные переменные объявлять неконстантными? Или только классы с move конструкторами?

Не все, а те, которые возвращаются из функции по значению (и для которых перемещение отличается от копирования, т.е. для какого-нибудь инта никакой разницы нет).

А как же правило использовать const как можно чаще?

Не понял вопрос. Или миритесь с возможной потерей производительности, или поменяйте это "правило".

→ Ссылка