繁体   English   中英

C ++ constexpr数组查找:内存开销? 其他陷阱?

[英]C++ constexpr array lookup: memory overhead? Other gotchas?

我已经基于这个SO答案实现了constexpr 映射 数组查找,但是这让我想知道如果 映射 数组很大,内存开销会是什么样子,以及这种技术还可能存在其他陷阱,特别是如果constexpr函数在编译时无法解析。

这是一个人为的代码示例,希望可以使我的问题更加清楚:

example.h:

enum class MyEnum
{
  X0,
  X1,
  X2,
  X3,
  X4,
  X5
};

struct MyStruct
{
  const MyEnum type;
  const char* id;
  const char* name;
  const int size;
};

namespace
{
  constexpr MyStruct myMap[] = {
    {MyEnum::X0,"X0","Test 0", 0},
    {MyEnum::X1,"X1","Test 1", 1},
    {MyEnum::X2,"X2","Test 2", 2},
    {MyEnum::X3,"X3","Test 3", 3},
    {MyEnum::X4,"X4","Test 4", 4},
    {MyEnum::X5,"X5","Test 5", 5},
  };

  constexpr auto mapSize = sizeof myMap/sizeof myMap[0];
}

class invalid_map_exception : public std::exception {};

// Retrieves a struct based on the associated enum
inline constexpr MyStruct getStruct(MyEnum key, int range = mapSize) {
  return  (range == 0) ? (throw invalid_map_exception()):
          (myMap[range - 1].type == key) ? myMap[range - 1]:
          getStruct(key, range - 1);
};

example.cpp:

#include <iostream>
#include <vector>
#include "example.h"

int main()
{
  std::vector<MyEnum> enumList = {MyEnum::X0, MyEnum::X1, MyEnum::X2, MyEnum::X3, MyEnum::X4, MyEnum::X5};
  int idx;

  std::cout << "Enter a number between 0 and 5:" << std::endl;
  std::cin >> idx;

  MyStruct test = getStruct(enumList[idx]);

  std::cout << "choice name: " << test.name << std::endl;

  return 0;
}

输出:

Enter a number between 0 and 5:
1
choice name: Test 1

g++一起-std=c++14编译。

在上面的示例中,尽管getStruct是constexpr函数,但直到运行时它才能完全解析,因为在此之前idx的值是未知的。 使用优化标志进行编译时,这可能会改变内存开销,还是将myMap的全部内容包含在二进制文件中? 是否取决于所使用的编译器和优化设置?

另外,如果头文件包含在多个翻译单元中怎么办? myMap会在每个myMap中重复吗?

我想如果 映射 数组变得巨大和/或代码将在更多资源受限的环境(例如嵌入式设备)中使用,这可能很重要。

这种方法还有其他潜在的陷阱吗?

如果使用非常量表达式调用constexpr函数,它将在运行时调用该函数。

如果使用常量表达式调用getStruct ,则编译器只能在编译时调用该函数。 然后, getStruct函数将在运行时“不使用”,编译器可能会对其进行优化。 此时, myMap也将不被使用,并被优化。

就运行时大小而言,它实际上可能小于std::unordered_mapstd::map ; 它实际上存储了必要的最少信息。 但是它的查找时间会慢很多,因为它必须在O(N)时间中单独比较所有元素,因此它实际上不执行映射所要做的事情(减少查找时间)。

如果您想使其更有可能被优化,我将确保仅在常量表达式情况下使用它:

template<MyEnum key>
struct getStruct
{
    static constexpr const MyStruct value = _getStruct(key);
}

这是一些编译器输出,显示该映射已完全优化

关于将其包含在多个翻译单元中,由于您使用匿名命名空间来定义它,因此每一个都将复制它。 如果在所有这些代码中都对其进行了优化,则不会有开销,但是对于在运行时查找中使用的每个翻译单元,它仍然会重复。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM