c++ - 是否需要显式构造 char 数组的每个成员?

标签 c++ memory-management stl language-lawyer

考虑以下代码:

#include <memory>

template<typename Allocator>
char* allocate_array(Allocator alloc, size_t n)
{
    static_assert(std::is_same<typename Allocator::value_type, char>::value);
    char* data = alloc.allocate(n);

    // (1)
    for (size_t i=0; i<n; ++i) {
        new (data+i) char();
    }

    return data;
}

char* copy_array(size_t n, const char* original)
{
    char* copy = allocate_array(std::allocator<char>(), n);
    // (2)
    for (size_t i=0; i<n; ++i) {
        copy[i] = original[i];
    }
    return copy;
}

即使保证每个字符都写入 (2),由 (1) 标记的放置新初始化是否有必要防止程序出现未定义的行为? code> 才能被读取?或者可以安全删除吗?

请注意,即使在 -O3 上,这也没有被优化掉,我看到 gcc 和 clang 都会生成对 memset()memcpy( )

最佳答案

Is the placement-new initialization marked by (1) necessary to prevent the program from having undefined behaviour.

据我所知,技术上是可以的。

[basic.life]

The lifetime of an object of type T begins when:

  • storage with the proper alignment and size for type T is obtained, and
  • its initialization (if any) is complete (including vacuous initialization) ([dcl.init]),

... before the lifetime of an object has started but after the storage which the object will occupy has been allocated or, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any glvalue that refers to the original object may be used but only in limited ways. ... The program has undefined behavior if:

  • the glvalue is used to access the object, or
  • ...
<小时/>

Note that this is not being optimized away

您可以默认初始化,而不是对字符进行值初始化。那么它们的值将在分配之前保持不确定,因此不需要 memset。另外,有一个标准函数可以实现此目的,因此无需编写循环:

std::uninitialized_default_construct(data, data + n);

关于c++ - 是否需要显式构造 char 数组的每个成员?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58417141/

相关文章:

c++ - 如何修复 "no match for ' operator<<' in ' std::cout"错误?

c++ - 编译时得到错误: 'QtGui/QAction' file not found #include <QtGui/QAction>

c++ - malloc如何分配内存以及Heap的大小是多少?

C++ STL 映射,std::pair 作为键

c++ - 自定义 std::allocator_traits::construct

用于获取 JPEG 图像大小的 C++ 库

c++ - 使用 VerQueryValue 检索应用程序的文件描述

iphone - -(void)取消分配问题

C# - 释放对象使用的所有资源

c++ - GCC 3.42 和 VC2008 对待 std::transform 的方式不同,获取仿函数的引用或拷贝?