【问题标题】:Is it possible to create class String without using heap in C++?是否可以在不使用 C++ 中的堆的情况下创建类 String?
【发布时间】:2019-04-24 09:40:55
【问题描述】:

我想编写自己的 String 类,它的接口类似于 std::string。字符串类不应使用动态内存分配。

我需要一个c-tor:

String(char* ptrToFirstCharInTab, char* ptrToLastElementInTab);

并且应该有包含不同(不知道)元素数量的选项卡,所以我在编译时不知道大小。

在我看来这是不可能的,因为如果我们在编译之前不知道数组的大小,我们就无法在没有动态分配的情况下创建它 - 当然为 500 char 创建缓冲区,然后 String 类只能是 500 这不是我的期望.

你有什么想法吗?也许有什么方法可以创建我会缩小以适应的缓冲区吗?感谢您的帮助!

【问题讨论】:

  • 您的问题或多或少类似于“是否可以在不使用 C++ 内存的情况下创建类 String?”
  • @RobertHarvey,你的意思是“不使用动态内存”吗?
  • @RSahu 你为什么要这样做?
  • 除非您有某种限制,否则无法避免动态分配。您是否有理由要避免动态分配?另外,你可能想看看小字符串优化
  • 我相信你是对的。动态大小 = 动态分配。

标签: c++ class memory-management stack static-allocation


【解决方案1】:

你问:

是否可以在 C++ 中不使用堆来创建 String 类?

事实上,是的,可以通过使用_alloca 或类似的平台相关函数在堆栈上动态分配内存。有关更多详细信息,请参见其他答案: C++ How to allocate memory dynamically on stack?

我建议不要这样做,并且在开始之前绝对确定这是最好的选择。

更新: 我使用 gcc 创建了一个带有内联构造函数的示例,用于演示目的:

编译器资源管理器链接: https://godbolt.org/z/M1F5VD

完整代码:

#include <alloca.h>

struct String {
  __attribute__((always_inline)) inline String(size_t size) {
     bytes= static_cast<char*>(alloca( size ));// alloca() memory gets allocated here
  }
  char* bytes;
};

int workWithString( ) 
{
   //std::string teststr("test");
   String mystrclass(1000);
   mystrclass.bytes[0] = 'a';
   mystrclass.bytes[1] = 0;
   return 0;
}  // alloca() memory only gets freed here



int main() {
    return workWithString();
   }

【讨论】:

  • 但是可用性非常有限 - 你如何将字符串返回给调用函数?
  • 之前看到过这个问题,但还是不确定_alloca能解决这个问题吗?如果我在我的 c-tor 中使用 _alloca,它将“在你离开函数时释放它的内存”。在 c-tor 结束后我将如何获得这个 char 数组?
  • @Aconcagua 在堆栈上我想?
  • @MarcinNurzyński 我不确定,您只需要在外部进行分配 - 其他一切都可以在 c-tor 内部处理,也许如果它总是内联 - 我自己在使用 _alloca 方面的经验为零.
  • @darune 如果函数 f 自己确定大小,然后适当地创建字符串?您必须将任何此类函数分成两部分('f_init` 来确定大小,然后是 alloca,然后 f_fini 来填充对象)。在最坏的情况下,您需要双重层次的函数调用。怀疑这是否真的可行......
【解决方案2】:

我对你的问题有点困惑。您希望std:: string 没有堆且没有大小限制。很抱歉给你带来这个:你不能拥有无限的记忆。

如果你有一个内存池你想专门用于字符串而不是每个字符串的固定大小,分配器可以这样做。 容器的默认分配器是新的,但是您可以替换它而无需复制字符串的内部结构。

【讨论】:

    【解决方案3】:

    你问:

    你有什么想法吗?也许有什么方法可以创建我会缩小以适应的缓冲区?

    理论上,是的,你可以。您可以使用预先分配的缓冲区作为堆内存。但是,您必须编写自己的代码来管理该缓冲区。可行,但我不推荐。

    【讨论】:

    • 如果字符串需要比缓冲区大怎么办?
    • +1 我正准备做一些复杂的例子,将 new 放置到全局 int8_t mem[1024*1024];
    • @NathanOliver 我想它应该抛出
    • @NathanOliver 就像动态分配的字符串需要比堆大一样:P
    • @MarcinNurzyński,收缩不是正确的做法。当您将该缓冲区用作仅String 或其他对象的堆内存时,也完全取决于您。
    猜你喜欢
    • 2014-06-17
    • 2019-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多