C++11 自动。从 float 转换为 long
C++11 auto. convert from float to long
是否可以将 foo 从 float 转换为 long(反之亦然)?
auto foo = float(1234567891234.1234);
cout << "foo: " << foo << endl;
foo = long(1234567891234.1234);
cout << "foo: " << foo << endl;
输出总是:
foo: 1.23457e+12
foo: 1.23457e+12
不是你写的那样。首先,
auto foo = float(1234567891234.1234);
使用自动类型推导规则推断RHS的类型,结果为float
。一旦完成,foo
的类型就是 float
并且是固定不变的(C++ 是 statically typed,不像 Python)。当你下次写
foo = long(1234567891234.1234);
foo 的类型仍然是 float
,并没有神奇地更改为 long
。
如果你想模拟一个 "change" 类型,你最多可以执行一个转换:
cout << "foo (as long): " << static_cast<long>(foo) << endl;
或使用附加变量
long foo_long = foo; // again you may have a loss of precision
但要注意浮点表示可能导致的精度损失。
如果您可以访问 C++17 编译器,则可以使用 std::variant<long, float>
(类型安全的联合)在类型之间切换。如果没有,你可以只使用像
这样的普通旧联合
#include <iostream>
union Foo
{
float f;
long l;
};
int main()
{
Foo foo;
foo.f = float(1234567891234.1234); // we set up the float member
std::cout << "foo: " << foo.f << std::endl;
foo.l = long(1234567891234.1234); // we set up the long member
std::cout << "foo: " << foo.l << std::endl;
}
或者,您可以使用类型擦除技术,例如
#include <iostream>
int main()
{
void *foo; // we will store the object via this pointer
foo = new int{42};
std::cout << *(int*)foo << '\n';
operator delete(foo); // don't do delete foo, it is undefined behaviour
foo = new float{42.42};
std::cout << *(float*)foo << '\n';
operator delete(foo); // don't do delete foo, it is undefined behaviour
}
上面代码的现代版本可以用 std::shared_ptr
重写,例如
#include <iostream>
#include <memory>
int main()
{
std::shared_ptr<void> foo{new int{42}};
std::cout << *(int*)foo.get() << '\n';
foo.reset(new float{42.42});
std::cout << *(float*)foo.get() << '\n';
}
A std::unique_ptr<void>
将无法工作,因为只有 std::shared_ptr
实现了类型擦除。
当然,如果您真的不关心存储大小等,只需使用 2 个单独的变量。
是否可以将 foo 从 float 转换为 long(反之亦然)?
auto foo = float(1234567891234.1234);
cout << "foo: " << foo << endl;
foo = long(1234567891234.1234);
cout << "foo: " << foo << endl;
输出总是:
foo: 1.23457e+12 foo: 1.23457e+12
不是你写的那样。首先,
auto foo = float(1234567891234.1234);
使用自动类型推导规则推断RHS的类型,结果为float
。一旦完成,foo
的类型就是 float
并且是固定不变的(C++ 是 statically typed,不像 Python)。当你下次写
foo = long(1234567891234.1234);
foo 的类型仍然是 float
,并没有神奇地更改为 long
。
如果你想模拟一个 "change" 类型,你最多可以执行一个转换:
cout << "foo (as long): " << static_cast<long>(foo) << endl;
或使用附加变量
long foo_long = foo; // again you may have a loss of precision
但要注意浮点表示可能导致的精度损失。
如果您可以访问 C++17 编译器,则可以使用 std::variant<long, float>
(类型安全的联合)在类型之间切换。如果没有,你可以只使用像
#include <iostream>
union Foo
{
float f;
long l;
};
int main()
{
Foo foo;
foo.f = float(1234567891234.1234); // we set up the float member
std::cout << "foo: " << foo.f << std::endl;
foo.l = long(1234567891234.1234); // we set up the long member
std::cout << "foo: " << foo.l << std::endl;
}
或者,您可以使用类型擦除技术,例如
#include <iostream>
int main()
{
void *foo; // we will store the object via this pointer
foo = new int{42};
std::cout << *(int*)foo << '\n';
operator delete(foo); // don't do delete foo, it is undefined behaviour
foo = new float{42.42};
std::cout << *(float*)foo << '\n';
operator delete(foo); // don't do delete foo, it is undefined behaviour
}
上面代码的现代版本可以用 std::shared_ptr
重写,例如
#include <iostream>
#include <memory>
int main()
{
std::shared_ptr<void> foo{new int{42}};
std::cout << *(int*)foo.get() << '\n';
foo.reset(new float{42.42});
std::cout << *(float*)foo.get() << '\n';
}
A std::unique_ptr<void>
将无法工作,因为只有 std::shared_ptr
实现了类型擦除。
当然,如果您真的不关心存储大小等,只需使用 2 个单独的变量。