G ++编译器中的奇怪的隐式转换警告

``````// Constructs a 2D vector from XY-coordinates.
inline vector2(float x, float y) : x_(x), y_(y) { }

// Constructs a 2D vector from polar coordinates
static vector2 polar(float r, float phi) {
return {r * cos(phi), r * sin(phi)};
}
``````

``````vector2.h:37:23: warning: narrowing conversion of ‘(((double)r) * cos(((double)phi)))’ from ‘double’ to ‘float’ inside { } [-Wnarrowing]
return {r * cos(phi), r * sin(phi)};
~~^~~~~~~~~~
``````

``````// Constructs a 2D vector from polar coordinates
static vector2 polar(float r, float phi) {
return vector2(r * cos(phi), r * sin(phi));
}
``````

Why does this warning appear? Does it mean that a compiled program will do an unnecessary conversion from `float` to `double` and back to `float`?

• 背后的孤独 回复

You are not using the correct `cos` and `sin`

``````#include <cmath>

class vector2 {
public:
float x_, y_;
// Constructs a 2D vector from XY-coordinates.
inline vector2(float x, float y) : x_(x), y_(y) { }
};

// Constructs a 2D vector from polar coordinates
static vector2 polar(float r, float phi) {
return {r * std::cos(phi), r * std::sin(phi)};
}
``````

Using the `std::cos` and `std::sin` gives the correct result as they are overload like this:

``````double cos (double x);
float cos (float x);
long double cos (long double x);
double cos (T x);           // additional overloads for integral types
``````
• 蜡笔小舅@ 回复

Judging from the warning you present it seems that you are using a `cos()` whose return type is `double` (8 bytes usually), so when you use it's result in an arithmetic operation with a `float` (4 bytes usually) the implicit conversion is from `float` to `double` (smaller to bigger type).

If you then store it in a `float` there is an implicit conversion from a bigger type to a smaller type with possible data loss, hence the warning.

由于我们没有您的全部代码，因此很难确定，但这似乎是事实。

``````#include <iostream>
#include <cmath>

using std::cout, std::endl, std::cos; // (C++17 comma separated)

int main(){
float x = 2.0;

cout << sizeof(float) << endl;  // 4
cout << sizeof(double) << endl << endl; // 8

auto y = cos(20) * x;  // overloaded --> double cos (double x(conversion)); C++11
float d = cos(20) * x;  // overloaded --> float cos (float x); C++11

cout << sizeof(y) << endl;  // 8
cout << sizeof(d) << endl;  // 4
}
``````

在这里一切正常，调用适当的重载函数，在您看来，这似乎没有发生。

• yyzs1995 回复

如果您发布整个源代码，将很有帮助。

根据您发布的内容，我假设您没有类似的内容

``````using namespace std;
``````

So `cos()` and `sin()` are the old C versions. They both expect an input of type `double`. `cosf()` and `sinf()` are the function expecting a float. Since you are using c++ you want to use the STL functions and not the old C ones.

所以做以下

``````static vector2 polar(float r, float phi) {
return {r * std::cos(phi), r * std::sin(phi)};
}
``````

STL函数是重载，因此它们将float和double作为输入，而没有任何隐式转换。