【问题标题】:C++ adaptive type deductionC++自适应类型推导
【发布时间】:2020-02-29 04:28:32
【问题描述】:

最近,我一直在玩 C++ 的类型推导。这样做时,我遇到了一些奇怪的事情。当我运行这段代码时:

#include <iostream>
using namespace std;

int main() {
    auto n = 40;
    auto factorial = 1;

    for(int i = 1; i <=n; ++i)
    {
        factorial *= i;
    }

    cout << "Factorial of " << n << " = " << factorial <<endl;   
    cout << "Size of factorial: " << sizeof(factorial) << endl; 
    return 0;
}

它会打印出来:

Factorial of 40 = 0
Size of factorial: 4

所以很明显存在缓冲区溢出,所以factorial0。但我不明白的是,为什么 auto 没有适应unsigned long long 之类的东西,以及为什么它保持为int(4 个字节)?有没有办法解决这个问题?

【问题讨论】:

  • "对于变量,指定正在声明的变量的类型将自动从其初始化程序中推导出来。" en.cppreference.com/w/cpp/language/auto 类型只是从初始化器推导出来的,而不是从以后对变量的任何使用推导出来的。
  • @John -- 谢谢。有什么解决方法吗?
  • “我需要推断类型”为什么?听起来像一个XY问题。如果我们有更多关于您为什么需要它的背景信息,我们或许可以提供解决方案。
  • 另外,根据我的计算器,我认为 40 阶乘是 8.1591528e+47。 ULL 只能保证最多处理 1.8446744e+19。你需要某种大整数库。
  • 我们很清楚——像这样声明为局部变量的基本类型是使用自动存储分配的。这意味着编译器在编译时为变量分配一定数量的大小。随着数字变大,该空间无法增长。如果您需要增加数量,您需要一个智能对象,该对象知道何时需要增加并可以根据需要处理动态内存分配。

标签: c++ integer-overflow type-deduction


【解决方案1】:

在 C++ 中,类型只是编译时的概念。当你真正开始运行程序时,它已经忘记了变量是什么类型;它无法在运行时适应。

你能做的最好的就是使用某种bignum type,它会根据需要自动增长,但它仍然保持相同的类型。

【讨论】:

  • 长话短说,如果您需要变量为特定类型,请不要使用auto
【解决方案2】:

所以很明显有缓冲区溢出

乘法结果溢出了,但是这里没有缓冲区溢出,也就是你往缓冲区中写入更多数据的时候

为什么 auto 不适应 unsigned long long 之类的东西,为什么它保持为 int(4 字节)?有没有办法解决这个问题?

1 是一个 int 字面量,因此很明显,如果您使用 auto factorial = 1;,它将创建一个 int 变量并为该变量保留固定数量的内存。大小无法更改,因为如果增加它,它将被淹没到附近的变量中

如果您想要动态调整大小的功能,那么您可以通过在堆上分配内存来自行处理,就像 std::vectorstd::unordered_map 这样的容器所做的那样。这需要更多的内存和 CPU 资源,这意味着它们不能应用于基本的 POD 类型,因为它们应该是快速的并且尽可能接近硬件。如果您想要大整数运算,请使用arbitrary-precision 库,如GMPBoost.Multiprecision。或阅读 标签了解更多信息

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-12
    • 2018-10-30
    • 2011-10-07
    • 2013-03-22
    相关资源
    最近更新 更多