【问题标题】:std::string and placement newstd::string 和新位置
【发布时间】:2014-05-27 01:35:58
【问题描述】:

我发现了这个在 C++ 中使用placement new 的例子,这对我来说没有意义。 我认为这段代码很容易出现异常,因为可能会使用比分配更多的内存。

char *buf  = new char[sizeof(string)];
string *p = new (buf) string("hi");

如果 "string" 是 C++ STD::string 类,那么 buf 将获得分配 空字符串对象的大小(我的编译器给出 28 个字节), 然后我看到的方式,如果你用更多的字符初始化你的字符串,你可能会 超过分配的内存。例如:

string *p = new (buf) string("hiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii");

在我的 VS 上,这似乎仍然有效,我不确定这是不是因为 以某种方式放弃了异常,或者我根本不明白字符串是如何工作的。

有人可以帮忙澄清一下吗?

【问题讨论】:

  • string("hiiii...") 运行时,它可能会执行new char[] 来获得额外的内存来存储文本,如果抛出那么重要的是p 不是deleted(那将是未定义的行为)但bufdelete[]ed(否则会出现内存泄漏)。所以一切都好 - 容易出错,即使不是“容易发生异常”。

标签: c++ string placement-new


【解决方案1】:

您误解了 std::string 的(典型)内部实现。通常它是这样实现的:

class string {
protected:
    char *buffer;
    size_t capacity;
    size_t length;

public:
    // normal interface methods
};

关键是有两个不同的内存块:一个用于string 对象本身,包含上面显示的成员,另一个用于字符串的内容。当您放置new 时,只有字符串对象被放入提供的内存中,而不是buffer 的内存,其中存储了字符串的内容。这是由string 类根据需要单独自动分配的。

【讨论】:

  • Nit-pick:我查看了一些标准库实现,它们都是用char* end_; 而不是length() 实现的,这意味着典型的迭代ala for (i = s.begin(); i != s.end(); ++i) 将有一个微不足道的便宜的end(),但size() 需要指针减法。没什么大不了的,也不是特别相关,但恕我直言,值得你记住......
  • @TonyD VS8 和 G++ 4.3.4 使用容量和长度字段,而不是 end 字段。无论如何,这个答案并不是一个关于如何有效实施std::string 的教程或辩论,而是一个便于理解的教学示例。
【解决方案2】:

sizeof 返回的大小是存储类成员所需的字节数,并带有一些实现定义的填充。必须先分配内存,然后才能调用 std::string 的构造函数。

但是,当构造函数运行时,它可能会分配更多的内存,这确实是为了存储大字符串而必须的。该内存量不属于sizeof 大小,您无需自己分配。

【讨论】:

  • 这就是我所缺少的。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-18
  • 2015-08-11
  • 1970-01-01
  • 2015-03-27
  • 2017-10-28
  • 2013-11-16
  • 2012-10-14
相关资源
最近更新 更多