相关疑难解决方法(0)

放置新开始创建的平凡类型的生命周期在什么时候开始?

在潜入动态记忆的过程中,我发现看起来矛盾的是琐碎的类型如何开始它们的生命.考虑一下片段

void* p = ::operator new(sizeof(int));  // 1
// 2
new (p) int; // 3
Run Code Online (Sandbox Code Playgroud)

什么时候int开始它的生命?

  1. 仅获取存储,::operator new指定具有效果(来自[new.delete.single])

    new-expression调用的分配函数用于分配大小的存储字节.[...]分配适当对齐的存储空间以表示该大小的任何对象,前提是对象的类型没有新扩展的对齐方式.

    鉴于获取存储不足以创建对象,int因此无法在此处开始其生命周期.

  2. 此时,int已经获得了适合的存储空间.

  3. int是由新位置创建的.但不知何故,它的生命没有从这里开始,因为来自[basic.life]

    [...]如果一个对象属于类或聚合类型,并且它或其子对象之一由除了普通默认构造函数之外的构造函数初始化,则称该对象具有非空的初始化.类型对象的生命周期从以下时间T开始:

    • 获得具有适当对齐和类型大小的存储T,并且

    • 如果对象具有非空的初始化,则其初始化完成[...]

    int既不是类也不是聚合类型,因此它具有空的初始化.因此,只有第一颗子弹适用.然而,这显然不是在获得存储时,因此不能在其寿命开始时.

一些背景

分配器需要在不构造其元素的情况下返回内存.然而,这对于琐碎的类型来说没有意义.的影响a.allocate(n)a对类型的分配器对象T

n为类型的T对象分配内存,但不构造对象.

c++ placement-new object-model language-lawyer

7
推荐指数
1
解决办法
196
查看次数

std::start_lifetime_as() 的实现

在 C++20 中接受P0593R6(“为低级对象操作隐式创建对象”)后,C++23 将得到std::start_lifetime_as()“完成 [P0593R6] 中提出的功能”(参见P2590R2P2679R2cppreference C++ 23 功能测试页)。

参考实现是什么样子std::start_lifetime_as()的?

这样的事情就足够了,还是还有更多?

#include <cstddef>
#include <new>

template<class T>
    T* start_lifetime_as(void* p) noexcept
{
    new (p) std::byte[sizeof(T)];
    return static_cast<T*>(p);
}
Run Code Online (Sandbox Code Playgroud)

c++ lifetime strict-aliasing undefined-behavior c++23

7
推荐指数
2
解决办法
757
查看次数

可以memcpy为std :: aligned_storage吗?

std :: aligned_storage :: type是POD类型.POD类型可以memcpy.但是,如果将新的非平凡可复制类型放置到std :: aligned_storage会发生什么?它能记得那个std :: aligned_storage吗?

非平凡可复制类型(非POD类型)不能memcpy,行为未定义.如果std :: aligned_storage memcpy是非平凡可复制的类型,它是否也是未定义的行为?

#include <new>
#include <type_traits>
#include <cstring>
#include <iostream>

struct y { int a; } ;

// non-trivially-copyable
struct t
{
    y a;
    int* p;
    t(){ p = new int{ 300 }; }
    t( t const& ){ a.a += 100; }
    ~t(){ delete p; }
};

int main()
{   // Block 1
    { 
        t a; a.a.a = 100;
        t b; b.a.a = 200;
        // std::memcpy(&b,&a,sizeof(t));  // abort...non-trivially-copyable
    } …
Run Code Online (Sandbox Code Playgroud)

c++ memcpy object-lifetime c++14

5
推荐指数
1
解决办法
495
查看次数

新标准中的 memcpy 生命周期初始化规则有哪些变化(如果有)?

据我所知,memcpy进入未初始化的存储不能安全地用于创建源对象的副本。

但是,在去年 open-std WG21“ub”列表上的这个线程中,参与者提到了新的 memcpy 生命周期启动规则

这似乎没有上升到错误报告的级别,但它可能与新的 memcpy 生命周期启动规则有关。他们会为源字节和目标字节分配一些静态类型吗?

Based on the context of the question and small amount of type-erasure example code, it appears that it may be related to creating new objects in aligned_storage via memcpy.

Search as I might, I can't find a reference to the new rules. I'm particularly curious if they only apply to replacing the contents of an already created object, or if they change …

c++ memcpy object-lifetime language-lawyer c++17

4
推荐指数
1
解决办法
298
查看次数

我可以隐式创建一个可复制的类型吗

我的问题是这样的:

假设类型T是可复制的。...可以在不调用构造函数的情况下“创建”该类型的实例。

#include <type_traits>
#include <cstring>

using T = int; // T can be any trivially copyable type


T create(const T& other)
{
    std::aligned_storage_t<sizeof(T),alignof(T)> my_T;

    std::memcpy(&my_T,&other,sizeof(T));

    return *reinterpret_cast<T*>(&my_T);
}
Run Code Online (Sandbox Code Playgroud)

这是已定义的行为,还是只能复制到T类型的现有对象中?

c++ copy memcpy language-lawyer c++14

2
推荐指数
1
解决办法
68
查看次数

复制位模式:浮动到uint32_t

float值的位模式复制到a uint32_t或反之亦然(不是将它们转换),我们可以使用std::copy或者逐字节复制位memcpy.另一种方法是使用reinterpret_cast如下:

float f = 0.5f;
uint32_t i = *reinterpret_cast<uint32_t*>(&f);
Run Code Online (Sandbox Code Playgroud)

要么

uint32_t i;
reinterpret_cast<float&>(i) = 10;
Run Code Online (Sandbox Code Playgroud)

然而,有一个声称reinterpret_cast上面使用的两个,调用未定义的行为.

真的吗?怎么样?

c++ primitive-types undefined-behavior reinterpret-cast

0
推荐指数
1
解决办法
378
查看次数

普通旧数据和`std :: memcpy`对齐问题

试图回答另一个问题,我提出了一个解决方案,用于std::memcpy()将通用类型存储在chars 的缓冲区中.

我怀疑存储POD可能存在内存对齐问题(我知道有非POD类型,因为std::string非常非常危险).

简而言之:以下程序存在内存对齐问题?

如果它们是,那么可以写一些类似的东西(将POD值存储在char缓冲区中)是安全的吗?如何?

#include <cstring>
#include <iostream>

int main()
 {
   char  buffer[100];

   double  d1 { 1.2 };

   std::memmove( buffer + 1, & d1, sizeof(double) );

   double  d2;

   std::memmove( & d2, buffer + 1, sizeof(double) );

   std::cout << d2 << std::endl;

   return 0;
 }
Run Code Online (Sandbox Code Playgroud)

c++ memory-alignment memcpy

0
推荐指数
1
解决办法
405
查看次数