gpt4 book ai didi

c++ - "constructing"一个可以用 memcpy 简单复制的对象

转载 作者:可可西里 更新时间:2023-11-01 15:05:27 24 4
gpt4 key购买 nike

在 C++ 中,这段代码是否正确?

#include <cstdlib>
#include <cstring>

struct T // trivially copyable type
{
int x, y;
};

int main()
{
void *buf = std::malloc( sizeof(T) );
if ( !buf ) return 0;

T a{};
std::memcpy(buf, &a, sizeof a);
T *b = static_cast<T *>(buf);

b->x = b->y;

free(buf);
}

换句话说,*b是一个生命周期开始的对象吗? (如果是这样,它到底是从什么时候开始的?)

最佳答案

这是未指定的,由N3751: Object Lifetime, Low-level Programming, andmemcpy支持其中说:

The C++ standards is currently silent on whether the use of memcpy to copy object representation bytes is conceptually an assignment or an object construction. The difference does matter for semantics-based program analysis and transformation tools, as well as optimizers, tracking object lifetime. This paper suggests that

  1. uses of memcpy to copy the bytes of two distinct objects of two different trivial copyable tables (but otherwise of the same size) be allowed

  2. such uses are recognized as initialization, or more generally as (conceptually) object construction.

Recognition as object construction will support binary IO, while still permitting lifetime-based analyses and optimizers.

我找不到任何讨论过这篇论文的 session 记录,所以它似乎仍然是一个悬而未决的问题。

C++14 草案标准目前在 1.8 [intro.object] 中说:

[...]An object is created by a definition (3.1), by a new-expression (5.3.4) or by the implementation (12.2) when needed.[...]

我们没有使用 malloc 并且标准中涵盖的用于复制普通可复制类型的情况似乎只引用 3.9 部分中已经存在的对象 < em>[基本类型]:

For any object (other than a base-class subobject) of trivially copyable type T, whether or not the object holds a valid value of type T, the underlying bytes (1.7) making up the object can be copied into an array of char or unsigned char.42 If the content of the array of char or unsigned char is copied back into the object, the object shall subsequently hold its original value[...]

和:

For any trivially copyable type T, if two pointers to T point to distinct T objects obj1 and obj2, where neither obj1 nor obj2 is a base-class subobject, if the underlying bytes (1.7) making up obj1 are copied into obj2,43 obj2 shall subsequently hold the same value as obj1.[...]

这基本上就是提案所说的内容,所以这不足为奇。

dyp 从 ub 邮件列表 中指出了关于这个主题的精彩讨论:[ub] Type punning to avoid copying .

提案 p0593:为低级对象操作隐式创建对象

提案 p0593 试图解决这个问题,但 AFAIK 尚未经过审查。

This paper proposes that objects of sufficiently trivial types be created on-demand as necessary within newly-allocated storage to give programs defined behavior.

它有一些本质上相似的激励示例,包括当前具有未定义行为的当前 std::vector 实现。

它提出了以下隐式创建对象的方式:

We propose that at minimum the following operations be specified as implicitly creating objects:

  • Creation of an array of char, unsigned char, or std::byte implicitly creates objects within that array.

  • A call to malloc, calloc, realloc, or any function named operator new or operator new[] implicitly creates objects in its returned storage.

  • std::allocator::allocate likewise implicitly creates objects in its returned storage; the allocator requirements should require other allocator implementations to do the same.

  • A call to memmove behaves as if it

    • copies the source storage to a temporary area

    • implicitly creates objects in the destination storage, and then

    • copies the temporary storage to the destination storage.

    This permits memmove to preserve the types of trivially-copyable objects, or to be used to reinterpret a byte representation of one object as that of another object.

  • A call to memcpy behaves the same as a call to memmove except that it introduces an overlap restriction between the source and destination.

  • A class member access that nominates a union member triggers implicit object creation within the storage occupied by the union member. Note that this is not an entirely new rule: this permission already existed in [P0137R1] for cases where the member access is on the left side of an assignment, but is now generalized as part of this new framework. As explained below, this does not permit type punning through unions; rather, it merely permits the active union member to be changed by a class member access expression.

  • A new barrier operation (distinct from std::launder, which does not create objects) should be introduced to the standard library, with semantics equivalent to a memmove with the same source and destination storage. As a strawman, we suggest:

    // Requires: [start, (char*)start + length) denotes a region of allocated
    // storage that is a subset of the region of storage reachable through start.
    // Effects: implicitly creates objects within the denoted region.
    void std::bless(void *start, size_t length);

In addition to the above, an implementation-defined set of non-stasndard memory allocation and mapping functions, such as mmap on POSIX systems and VirtualAlloc on Windows systems, should be specified as implicitly creating objects.

Note that a pointer reinterpret_cast is not considered sufficient to trigger implicit object creation.

关于c++ - "constructing"一个可以用 memcpy 简单复制的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30114397/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com