Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/164.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 从std::aligned\u union\t获取指向包含对象的指针_C++ - Fatal编程技术网

C++ 从std::aligned\u union\t获取指向包含对象的指针

C++ 从std::aligned\u union\t获取指向包含对象的指针,c++,C++,我想在std::aligned\u union\t中使用placement构造一个任意类型的新对象。一旦构造成功,我希望能够返回指向构造对象的指针,而无需单独存储它。只要我确保将其转换为构造的原始类型,通过简单地重新解释std::aligned\u union\u t来执行此操作是否合法 以下例举上述内容的代码是否合法?是否有任何类型特征要求MyStruct应该满足?例如,它必须是一个豆荚吗 #include <type_traits> #include <memory>

我想在
std::aligned\u union\t
中使用placement构造一个任意类型的新对象。一旦构造成功,我希望能够返回指向构造对象的指针,而无需单独存储它。只要我确保将其转换为构造的原始类型,通过简单地重新解释std::aligned\u union\u t
来执行此操作是否合法

以下例举上述内容的代码是否合法?是否有任何类型特征要求
MyStruct
应该满足?例如,它必须是一个豆荚吗

#include <type_traits>
#include <memory>
#include <cstddef>
#include <exception>

struct MyStruct
{
    int value = 0;
};

constexpr size_t c_alignedUnionSize = 10;
std::aligned_union_t<c_alignedUnionSize, std::max_align_t> g_storage;

MyStruct* GetPtr()
{
    return reinterpret_cast<MyStruct*>(std::addressof(g_storage));
}

void Construct()
{
    if (sizeof(MyStruct) > sizeof(g_storage))
    {
        std::terminate();
    }

    auto ptr = new (std::addressof(g_storage)) MyStruct{};
    if (!ptr)
    {
        std::terminate();
    }

    GetPtr()->value = 123;
}

void Destroy()
{
    GetPtr()->~MyStruct();
}

int GetValue()
{
    return GetPtr()->value;
}

int main()
{
    Construct();
    auto value = GetValue();
    Destroy();
    return value;
}
#包括
#包括
#包括
#包括
结构MyStruct
{
int值=0;
};
constexpr size\u t c\u alignedUnionSize=10;
标准:对齐的联合存储;
MyStruct*GetPtr()
{
返回reinterpret_cast(std::addressof(g_存储));
}
void构造()
{
if(sizeof(MyStruct)>sizeof(g_存储))
{
std::terminate();
}
自动ptr=new(std::addressof(g_存储))MyStruct{};
如果(!ptr)
{
std::terminate();
}
GetPtr()->value=123;
}
无效销毁()
{
GetPtr()->~MyStruct();
}
int GetValue()
{
返回GetPtr()->值;
}
int main()
{
构造();
自动值=GetValue();
破坏();
返回值;
}

在这里重新解释投射应该是安全的。最新的标准草案说:

对象指针可以显式转换为不同类型的对象指针。当对象指针类型的prvalue
v
转换为对象指针类型“指向cv的指针
T
”时,结果是
static(v))
。[ 注:将“指针指向
T1
”类型的PR值转换为“指针指向
T2
”类型(其中
T1
T2
是对象类型,其中
T2
的对齐要求不比
T1
的对齐要求更严格)并返回到其原始类型会产生原始指针值- 尾注 ]

相关问题:


  • 不幸的是,这是标准所禁止的。在C++标准中,代码> >从一个指针到对象A到另一个不同类型对象B的RealtType Case<代码>只有当两个对象是指针可转换的,即:

    时才被证明是有效的。 两个对象a和b是指针可相互转换的,如果:

    • 它们是相同的对象,或者

    • 一个是联合对象,另一个是该对象的非静态数据成员([class.union]),或者

    • 一个是标准布局类对象,另一个是该对象的第一个非静态数据成员,或者,如果该对象没有非静态数据成员,则是该对象的第一个基类子对象([class.mem]),或者

    • 存在一个对象c,使得a和c是指针可相互转换的,c和b是指针可相互转换的

    如果两个对象是指针可相互转换的,则它们具有相同的地址,并且可以通过
    重新解释
    从指向另一个对象的指针获取指向其中一个对象的指针[ 注意:数组对象及其第一个元素不是指针可相互转换的,即使它们具有相同的地址- 尾注 ]

    指针具有正确的类型和正确的值(内存地址)这一事实并不意味着它是一个有效的指针。这种令人惊讶的行为的典型示例如下:

    alignas(int) unsigned char buff[2*sizeof(int)];
    auto p1 = new(buff) int{};
    auto p2 = new(buff+sizeof(int)) int{};
    *(p1+1) = 10;//Undefined behavior
    //p1+1 does not point to *p2 even if p1 and p2 have same type and value.
    
    因此,要符合标准,必须存储
    new
    返回的指针值


    我找到了一个很好的解决方案,它包括将指针强制转换为整数类型和其他指针类型,这将导致实现定义的行为():

    reinterpret_cast(reinterpret_cast(地址of(g_存储));
    
    我认为您链接到的问题太老了。一个较新的相关问题是:“如果两个对象是指针可相互转换的,那么它们具有相同的地址,并且可以通过
    重新解释从指向另一个对象的指针获得指向一个对象的指针。”是否有任何地方标准明确提到两个不可相互转换的指针之间的
    reinterpret\u cast
    无效?@VittorioRomeo[…]当本文件省略任何明确定义[…]时,可能会出现未定义的行为该标准定义了指针互换性的概念,明确用于允许一些
    重新解释从一个指针类型到另一个指针类型,这一简单事实清楚地表明,其他
    重新解释
    没有定义!@VittorioRomeo实际上总是定义
    重新解释
    标准未描述的情况,结果可能是=>指针不是指向对象的指针。相关问题:
    reinterpret_cast<MyStruct*>(reinterpret_cast<std::uintptr_t>(addressof(g_storage));