Различные примечания для неинициализированного члена внутри общей лямбды в GCC 9 и GCC 10

Я заметил непоследовательное поведение в моем рабочем коде C++17 в отношении общих лямбда-выражений и примечаний. Наконец мне удалось разбить это на следующий минимальный пример.

Выдает примечание с x86_64 gcc 9.3, но НЕ с x86_64 gcc 10.1.

#include <string>
#include <iostream>

struct STR { int a; };

int main() 
{
    auto lambda = 
        []( const auto& executionContext )
        {
            if ( !executionContext.empty() )
                return;

            STR objSTR;
            objSTR.a = 666;
            std::cout << objSTR.a;
        };
    
    lambda( std::string{} );

    return 0;
}

Сообщение компилятора следующее:

<source>: In instantiation of 'main()::<lambda(const auto:1&)> [with auto:1 = std::__cxx11::basic_string<char>]':
<source>:19:31:   required from here
<source>:4:12: note: 'struct STR' has no user-provided default constructor
    4 |     struct STR { int a; };
      |            ^~~
<source>:4:22: note: and the implicitly-defined constructor does not initialize 'int STR::a'
    4 |     struct STR { int a; };
      |                      ^

Чем хороша заметка? Я правильно инициализирую свою структуру с помощью 666. Насколько мне известно, это правильный код C++ и не требует каких-либо примечаний/ссылок о/на возможные неинициализированные опасности.

Интересно, что если я сейчас заменю auto на std::string, заметка исчезнет полностью. Так вдруг здесь не нужна никакая заметка?

Не дает никаких примечаний с x86_64 gcc 9.3 и с x86_64 gcc 10.1.

#include <string>
#include <iostream>

struct STR { int a; };

int main() 
{
    auto lambda = 
        []( const std::string& executionContext )
        {
            if ( !executionContext.empty() )
                return;

            STR objSTR;
            objSTR.a = 666;
            std::cout << objSTR.a;
        };
    
    lambda( std::string{} );

    return 0;
}

Я могу ТОЛЬКО избавиться от примечания для общей лямбды, если использую инициализацию значения следующим образом:

Не дает никаких примечаний с x86_64 gcc 9.3 и с x86_64 gcc 10.1.

#include <string>
#include <iostream>

struct STR { int a; };

int main() 
{
    auto lambda = 
        []( const auto& executionContext )
        {
            if ( !executionContext.empty() )
                return;

            STR objSTR{}; //FORCED to add {} to get rid of the note
            objSTR.a = 666;
            std::cout << objSTR.a;
        };
    
    lambda( std::string{} );

    return 0;
}

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

Конкретный, однозначный вопрос:
=> Можете ли вы подтвердить, что это ошибка в GCC 9.3?

Онлайн-демо: https://godbolt.org/z/E7xeP91xd Флаги: -Wall -Wextra -O3 -std=c++17
Компилятор: x86_64 gcc 9.3/x86_64 gcc 10.1

Вы говорите «сообщение об ошибке», но это не сообщение об ошибке. Программа все еще компилируется. Это даже не похоже на предупреждение. Кажется, gcc 9 просто болтал о потенциально интересных вещах, которые он нашел.

Ted Lyngmo 08.08.2024 09:37

gcc прав в том, что говорит. Почему вы думаете, что это не так? Созданный компилятором конструктор не инициализирует член.

463035818_is_not_an_ai 08.08.2024 09:40

Я скорректировал свой пост. Но это также противоречивое поведение для заметок.

SoulfreezerXP 08.08.2024 09:44

В вашем примере я не вижу проблемы с отсутствующей заметкой, потому что этот член никогда не читается. Однако gcc 10.1 не выдает никаких результатов даже при использовании члена godbolt.org/z/8Eqj4n5hM

463035818_is_not_an_ai 08.08.2024 09:51

Я думаю, ты еще не совсем понял суть. Я думаю, что должна быть возможность создать экземпляр структуры БЕЗ инициализации ее напрямую с помощью {} без этого примечания. Однако это невозможно в универсальной лямбде в gcc 9. За пределами универсальной лямбды совершенно нормально НЕ использовать {}. Здесь вы не получите НИКАКОЙ записки. Так почему же примечание отсутствует за пределами общей лямбды и почему оно полностью отсутствует в gcc10? godbolt.org/z/6WGar76W1

SoulfreezerXP 08.08.2024 11:02

Я до сих пор не понимаю, что плохого в создании этой заметки. И я не понимаю, как я могу упустить момент, который вы только сейчас затронули? За пределами лямбды нет неинициализированного члена. хм? Должно быть, такая сегодня погода.

463035818_is_not_an_ai 08.08.2024 11:19

Примечание представляет собой неоправданный шум. Меня беспокоит то, что я получаю подсказки (и только в контексте шаблона), что мой POD имеет неинициализированные значения, хотя впоследствии я инициализирую все значения. GCC10, кажется, устранил этот шум. Ты все еще не видишь?

SoulfreezerXP 08.08.2024 11:30

Я еще раз немного отредактировал свой пост, чтобы, возможно, было яснее, что имеется в виду.

SoulfreezerXP 08.08.2024 13:13

@SoulfreezerXP В самом предупреждении нет ничего плохого. Компиляторы выдают их постоянно, например, «предупреждение: неиспользуемая переменная» и т. д. Компиляторы могут предупреждать.

user12002570 08.08.2024 13:24

Я действительно очень упускаю суть этого вопроса. Ни одна из версий GCC не является новой. Ни одна из версий не является ошибочной. Менее древняя версия немного более последовательна. Это могло быть совершенно непреднамеренно и, следовательно, не в журнале изменений.

MSalters 08.08.2024 13:56

Пожалуйста, прочитайте вопрос и ответьте или нет....но не голосуйте против ради развлечения. Я хочу знать, является ли это плохим поведением или нет.

SoulfreezerXP 08.08.2024 13:57

@MSalters адаптировал вопрос для вас

SoulfreezerXP 08.08.2024 14:09

@SoulfreezerXP Вопрос будет закрыт как основанный на мнении, если вы используете такие слова, как «это некрасиво». Теперь, чтобы сейчас ответить на ваш вопрос «Это ошибка?» Нет, это не ошибка. Составители могут предупредить. Возможно, вы видели такие предупреждения, как предупреждение: переменная объявлена, но не используется... и т. д. Все эти предупреждения являются действительными, и компиляторы могут их предупредить.

user12002570 08.08.2024 15:51

Здесь нет никаких предупреждений, только неуместные ПРИМЕЧАНИЯ. И это создает ненужный шум в моем контексте, поскольку я правильно инициализирую свою структуру.

SoulfreezerXP 08.08.2024 16:23

@SoulfreezerXP Вы сказали «предупреждение» в заголовке своего вопроса.

user12002570 08.08.2024 16:30

Это был не я. Наверное, кто-то другой неправильно адаптировал название. Я исправлю заголовок. Но из 1-го и 2-го моего комментария 6 часов назад должно быть понятно, что речь идет о заметках! И да, бросание заметки без надобности тоже может быть «багом».

SoulfreezerXP 08.08.2024 16:35

@SoulfreezerXP Возможно, именно поэтому они удалили его из поздних версий.

user12002570 08.08.2024 16:36

Возможно, но я хочу быть уверенным и получить ответ от профессионала.

SoulfreezerXP 08.08.2024 16:40

@SoulfreezerXP Думаю, тогда официальная страница gcc подошла бы больше.

user12002570 08.08.2024 18:44
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
19
104
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Примечание в GCC 9.3 о неинициализированном члене в структуре STR технически правильно, поскольку конструктор по умолчанию не инициализирует int a.

В GCC 10.1 эта проверка, возможно, была смягчена или улучшена распознавание контекста для общих лямбда-выражений. Инициализация objSTR с помощью {} — хорошая практика для обеспечения инициализации членов. Если примечание раздражает, но безвредно, вы можете спокойно проигнорировать его или явно инициализировать структуру. Различные версии компилятора часто имеют различия в поведении предупреждений и примечаний, что может объяснить наблюдаемое несоответствие.

Я принимаю это как ответ, потому что это, по крайней мере, в некоторой степени отвечает на вопрос.

SoulfreezerXP 08.08.2024 18:59

Разве GCC 9.3 не ведет себя здесь неправильно? Я понимаю, что моя структура не инициализируется int STR::a

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

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