【问题标题】:C++11 - bad_alloc on a constexprC++11 - constexpr 上的 bad_alloc
【发布时间】:2013-11-17 07:03:22
【问题描述】:

带有位掩码的数组非常流行,通常它们编写起来很乏味,而且它们使代码的可读性降低,我想用constexpr 生成它们,这是我的尝试

#include <iostream>
#include <cstdint>
#include <vector>
#include <utility>

typedef uint32_t myT;

template <typename T>
constexpr std::vector<T> vecFarm(T &&lower, T &&upper, T &&step) {
  // std::cout << lower << " " << upper << " " << step << "\n";
  std::vector<T> v;
  if (lower < upper) {
    for (T count = lower; count < upper; count += step) {
      v.push_back(count);
    };
  }
  return (v);
}

int main() {

  std::vector<myT> k(std::move(vecFarm(myT(0), ~(myT(0)), myT(256)))); //why
  // this doesn't work ?
  // std::vector<myT> k(std::move(vecFarm(myT(0), ((~(myT(0))) >> 16), myT(256))));
  // but this one works
  // let's see what we got
  for (const auto &j : k) {
    std::cout << j << " ";
  }
  std::cout << "\n";

  return (0);
}

我使用了std::move,未命名的对象和constexpr,这段代码编译得很好

g++-4.8 -O3 -std=c++11 -pthread -Werror -Wall -Wextra

但由于bad_alloc,它在运行时失败,我可以看到我的“小”应用程序分配了大量空间。

也许错误很大,我看不到,但为什么这不起作用?

为什么我的应用程序在运行时进行分配?不应该在编译时计算所有内容吗?我期待这可能会在编译时而不是在运行时失败。

【问题讨论】:

    标签: c++ c++11 constexpr


    【解决方案1】:

    std::bad_alloc 通常意味着它无法分配更多内存。将您的代码更改为以下内容会告诉您原因:

    for (T count = lower; count < upper; count += step) {
        std::cout << "count:" << count << "\n";
        std::cout << "upper:" << upper << "\n";
    };
    

    当我测试它时,这会在第一个循环中打印以下内容:

    count:0
    upper:4294967295
    

    换句话说,在 count &lt; upper 失败和 for 循环停止之前,您还有很长的路要走,尤其是因为您每次只添加 256

    此外,为了在编译时评估 constexpr 函数,存在某些 conditions it has to fullfil。例如,its return type must be LiteralType,你的函数返回std::vector,同样,exactly one return statement that contains only literal values, constexpr variables and functions.,你有一个复合语句。因此,您的函数无法在编译时进行评估。

    另外,请注意,如果您不满足这些条件,constexpr 限定符将被忽略,但如果您打开 -pedantic,它应该可以为您提供更好的诊断。

    【讨论】:

    • 值得注意的是,如果他将函数设为非模板,他的代码将根本无法编译。
    • 事实上我专注于我的类型uint32_t 的范围,我忘记了向量也需要内存......;因此,如果我想在 constexpr 限定符被忽略的情况下中断编译,那么最好的方法是什么?
    • @user2485710: It's not possible.
    • @JesseGood 既不是 type_traits 也不是断言?什么都不是?
    • @user2485710:有几个tricks shown here,如果你尝试使用需要常量表达式的函数,它当然会失败,但一般来说没有什么可能(虽然我认为有是一个 C++ 提议来改变这一点)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-27
    • 2013-07-17
    • 1970-01-01
    • 1970-01-01
    • 2019-06-22
    相关资源
    最近更新 更多