Поделиться через


Предупреждение компилятора (уровень 1) C4838

Преобразование из "type_1" в "type_2" требует сужения преобразования

Неявное сужение преобразования было найдено при использовании статистической или инициализации списка.

Язык C позволяет неявно сужать преобразования в назначениях и инициализации, и C++ следует примеру, несмотря на то, что неожиданное сужение является причиной многих ошибок кода. Чтобы сделать код более безопасным, стандарт C++ требует диагностического сообщения, когда сужающее преобразование происходит в списке инициализации. В Visual C++диагностика — ошибка компилятора C2397 при использовании синтаксиса универсальной инициализации, поддерживаемого начиная с Visual Studio 2015. Компилятор создает предупреждение C4838 при использовании синтаксиса инициализации списка или статистической инициализации, поддерживаемого Visual Studio 2013.

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

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

// C4838.cpp -- C++ narrowing conversion diagnostics
// Compile by using: cl /EHsc C4838.cpp

struct S1 {
    int m1;
    double m2, m3;
};

void function_C4838(double d1) {
    double ad[] = { 1, d1 }; // OK
    int ai[] = { 1, d1 };    // warning C4838
    S1 s11 = { 1, 2, d1 };   // OK
    S1 s12 { d1, 2, 3 };     // warning C4838
    S1 s13 { static_cast<int>(d1), 2, 3 }; // possible fix for C4838
}