警告 C4244:"参数":从"double"转换为"const int",可能会丢失数据

warning C4244: 'argument' : conversion from 'double' to 'const int', possible loss of data

本文关键字:数据 int 参数 C4244 double 警告 转换 const      更新时间:2023-10-16

我正在定义'*'运算符以使用'NumericArray'类模板。代码如下:

template <class T>
NumericArray<T> NumericArray<T>::operator * (const T& factor) const
{
    NumericArray<T> newArray(Size());
    for (int i = 0; i < Size(); i++)
        newArray[i] = factor * GetE(i);
    return newArray;
}

当"factor"参数为double时,我尝试将类型为"int"(NumericArray)的"NumericArray"与"*"运算符一起使用时:

intArray1 = intArray1*2.5;

我收到以下编译器警告:

warning C4244: 'argument' : conversion from 'double' to 'const int', possible loss of data

"factor"arg在与"NumericArray"对象的元素相乘之前,会从2.5截断为2(一个int)。有没有办法防止这种情况发生?我认为在C++中,这只是默认协议的一个简单问题,其中int*double=double。我错了吗?如果不是,为什么这不适用于这种情况?

intArray1 = intArray1*2.5;

我猜intArray1属于NumericArray<int>类型。如果是这样的话,那么T就是int。因此,在上面的表达式中,作为double2.5将被转换为int,因为它被作为参数传递给重载的operator*(const int&)

这也意味着,2.5(double)变为2(int),并且factor基本上是2。数据丢失!

解决此问题的一种方法是使用函数模板(作为类模板的成员)作为:

template<class T>   //this is for class templatwe
template<class U>   //this is for function template
NumericArray<T> NumericArray<T>::operator * (const U& factor) const
{                                           //^^^^^^^ it is U now!
     //your code
}

不要对template在上述定义中的两种用法感到惊讶。这些评论说明了他们的目的。如果你很好地理解了这一点,那么你也理解了参数现在是U而不是T,它可以独立于T,因此它可以是你作为参数传递给它的任何东西。就传递参数而言,没有数据丢失。

既然你知道intdouble的乘积原来是double,那么当你把double传递给函数时,为什么要从函数中返回NumericArray<int>呢?我认为如果参数是double,那么返回NumericArray<double>更有意义。因此,以下似乎是正确的实现:

template<class T>   //this is for class templatwe
template<class U>   //this is for function template
NumericArray<U> NumericArray<T>::operator * (const U& factor) const
{         //^^^ CHANGED
    NumericArray<U> newArray(Size());  //CHANGED HERE TOO!
    for (int i = 0; i < Size(); i++)
        newArray[i] = factor * GetE(i);
    return newArray;
}

等等!现在这样正确吗?如果TdoubleUint怎么办?上面的问题和前面的问题完全一样

所以这里是第三次尝试:

template<class T>   //this is for class templatwe
template<class U>   //this is for function template
NumericArray<decltype(std::declval<T>() * std::declval<U>())> 
     NumericArray<T>::operator * (const U& factor) const
{
    typedef decltype(std::declval<T>() * std::declval<U>()) R; //define R
    NumericArray<R> newArray(Size());  //CHANGED HERE!
    for (int i = 0; i < Size(); i++)
        newArray[i] = factor * GetE(i);
    return newArray;
}

因此返回类型为:

NumericArray<R>

其中R为:

decltype(std::declval<T>() * std::declval<U>());

这取决于CCD_ 27和CCD_。现在这是正确的,至少好多了。

希望能有所帮助。

您的模板代码要求参数和NumericArray元素具有相同的时间,这就是为什么C++在multipying之前将arg截断为2。

要解决这个问题,您应该编写类似的代码

template <class U> template<class T>
NumericArray<T> NumericArray<T>::operator * (const U& factor) const
{
  /***/
}