【问题标题】:Allocating memory and reinterpreting pointer using new in C++在 C++ 中使用 new 分配内存和重新解释指针
【发布时间】:2015-03-06 16:02:59
【问题描述】:

我想通过分配 n * sizeof(T) 个字节为 n T 个对象分配内存,并使用 new 获取指针。下面的代码有什么问题?

template <class T>
void foo(size_t n, const T& value)
{
    T* buffer = reinterpret_cast<T*>(new char[n * sizeof(T)]);
    for (int i = 0; i < n; i++) {
        buffer[i] = value;
        std::cout << buffer[i] << std::endl;
    }
    std::cout << "success" << std::endl;
}

如果我调用foo&lt;int&gt;(n, int());,但如果我调用foo&lt;std::string&gt;(n, std::string());,则会出现分段错误。

【问题讨论】:

  • 您无法将随机内存重新解释为字符串
  • T* 缓冲区 = 新 T[n];或者更好的是,使用矢量。事实上,你正在泄漏内存。
  • @ehang,是的,这显然可以解决问题,但它会调用默认初始化程序 T n 次,我只是想要一种方法来避免它。
  • 如果使用vector,可以指定默认值。在内部,它会为您调用placement new。

标签: c++ templates pointers memory


【解决方案1】:

您需要在内存中创建一个对象,而不仅仅是将未初始化的字节重新解释为一个对象。对于int,您将侥幸逃脱,因为分配只会覆盖那里的任何内容。 std::string 将(可能)包含无效的指针和大小,并且会认为这些指的是应该删除或替换为指定值的数据;因此崩溃了。

要在预分配的内存中创建对象,请使用placement-new而不是赋值:

new(&buffer[i]) T(value);

当你完成一个对象后,你必须在释放内存之前自己调用它的析构函数:

buffer[i].~T();

您可以通过 std::vector&lt;T&gt; buffer(n, value); 避免这种容易出错的舞蹈,它会在幕后完成所有这些操作,而不会打扰您。

【讨论】:

  • 啊,好吧,显然我忘了那里有一些垃圾,所以与放置新的位置相反,分配不起作用。太好了,谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-29
  • 2013-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多