C++11自动类型推导:将浮点数转换为长整型

3
能否将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

这不是问题,但是除非你需要它提供的额外功能,否则不要使用std::endl'\n'可以用来结束一行。 - undefined
1个回答

15

不是你写的那样。首先,

auto foo = float(1234567891234.1234);

使用自动类型推导规则来推断RHS的类型,结果是float。一旦完成这个过程,foo的类型就是float并且它已经确定了(C++是静态类型,不像Python)。下次写入时保留float类型。
foo = long(1234567891234.1234);

foo的类型仍然是float,它不会神奇地变成long

如果你想模拟一种类型的“改变”,你最多只能执行一个强制转换:

 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;
}

在Coliru上实时运行

或者,您可以使用一种类型抹消技术,例如

#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
}

在Coliru上实时运行

上述代码的现代版本可以使用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';
}

在Coliru上实时演示

一个std::unique_ptr<void>不起作用,因为只有std::shared_ptr实现了类型抹除。

当然,如果你并不真的关心存储大小等问题,那就只使用两个单独的变量。


能否这样做:foo = static_cast<long>(foo); 并将foo的类型转换为long?有没有其他方法可以实现这个目标? - undefined
4
不,正如我在答案中所说,“foo”的类型在程序运行期间始终为“float”。在C++中无法改变变量的类型。最接近的做法是使用std::variant<float,long>(C++17)。 - undefined
谢谢,你帮了我大忙。我几乎没指望你会再回复我,如果你看到这条消息的话。当foo是一个浮点数时,是否可能将其删除,然后重新初始化为长整型? - undefined
1
@djent 不,只有在使用联合体的情况下才会发生这种情况。如果你只是首先将其声明为float,它将始终保持为float。在C++中,变量的类型在编译时确定(即在程序运行之前),并且不会改变。你可以使用一种称为“类型擦除”的技术,在其中声明一个void*指针,然后将其转换为所需的类型,但首先尝试使用最简单和最清晰的代码。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接