Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.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++ C+中平凡类型的构造和初始化+;_C++_Initialization_Language Lawyer - Fatal编程技术网

C++ C+中平凡类型的构造和初始化+;

C++ C+中平凡类型的构造和初始化+;,c++,initialization,language-lawyer,C++,Initialization,Language Lawyer,A是可复制的,并且具有(A是其中之一,或者是一个工作方式类似的内置类) 由于要复制普通类型的对象,并且由于普通类型不会更改表示“”中的任何字节,以下代码(使用C++20概念)是否正确初始化传入对象的副本 #include <cstdlib> #include <cstring> #include <new> #include <type_traits> template <typename T> T* copy_trivial(T

A是可复制的,并且具有(A是其中之一,或者是一个工作方式类似的内置类)

由于要复制普通类型的对象,并且由于普通类型不会更改表示“”中的任何字节,以下代码(使用C++20概念)是否正确初始化传入对象的副本

#include <cstdlib>
#include <cstring>

#include <new>
#include <type_traits>

template <typename T>
T* copy_trivial(T orig) requires std::is_trivial_v<T>
{
    void* buf = std::aligned_alloc(alignof(T), sizeof(T));

    // Note the order of these statements
    std::memcpy(buf, &orig, sizeof(T));
    return new(buf) T;
}
#包括
#包括
#包括
#包括
模板
T*copy_triple(T orig)需要std::is_triple_v
{
void*buf=std::aligned_alloc(alignof(T),sizeof(T));
//请注意这些语句的顺序
标准:memcpy(基本单位和原始单位,大小单位(T));
返回新的(buf)T;
}
(,提供了几个实例)

这段代码似乎可以工作,因为将有一个具有正确对象表示形式的初始化对象。但是,假设初始化后什么也没有发生,对象是否会有一个²


1未在单个位置指定,但默认初始化的链接过程调用构造函数,构造函数必须是;隐式定义的构造函数;对于内置的平凡类型,递归在最底层

²中的注释表示会,但注释是非规范性的,这似乎只适用于非放置
的情况

以下代码(使用C++20概念)是否正确初始化传入对象的副本

#include <cstdlib>
#include <cstring>

#include <new>
#include <type_traits>

template <typename T>
T* copy_trivial(T orig) requires std::is_trivial_v<T>
{
    void* buf = std::aligned_alloc(alignof(T), sizeof(T));

    // Note the order of these statements
    std::memcpy(buf, &orig, sizeof(T));
    return new(buf) T;
}
不,没有

它确实返回指向有效
T
的指针,但标准中没有要求该
T
的值是
orig
值的副本

一般类型的默认初始化称为执行“无初始化”。但这与保存该内存的当前存储不同:[dcl.init]/12

当获得具有自动或动态存储持续时间的对象的存储时,该对象具有不确定值,如果未对该对象执行初始化,则该对象将保留不确定值,直到替换该值为止

请注意,它表示它保留了“一个不确定的值”,而不是“与该内存中的值相同”。如果没有明确的保护,标准不需要实现来保存内存的内容

考虑调试构建。为了捕获错误,“未执行初始化”的情况有时会用特定字节填充未初始化内存,以便您可以在访问未初始化内存时进行检测。只有在“不确定值”没有在内存中保留当前值的情况下,这才对实现合法

< C++中没有方法用另一个对象的字节拷贝复制对象。您可以在任意内存中执行memcpy,但不能在该内存中显示从该内存中获取其值的对象。您可以memcpy到现有对象中,但该对象已经初始化(除非在创建时未执行初始化)


因此,您最好将这两个语句的顺序颠倒过来。

注意:这个问题是受启发提出的,但为了避免
realloc
的复杂性,我对它做了一些简化。有趣的问题,但我很好奇:以这种方式构造代码,而不是先调用placement
new
,有什么可能的好处,接着是
memcpy
?@JohnZwinck,样本中的内存由
malloc
获得。如果它是由
realloc
(或可能用于C代码中的其他函数)获得的,那么在有机会放置
new
之前,复制就会发生。我假设调试生成会“在获得存储[…]时”填充未初始化的内存,而不是在每次默认初始化时。它还说“保留”一个不确定的值;在
memcpy
之后,我不确定是否还有不确定的值;同样,这是在获得存储之后。@DanielH:为对象获得存储发生在创建对象时。也就是说,作为
新表达式的一部分。仅通过调用
malloc
无法获取对象的存储。因此,虽然
malloc
可以填充这些值,但placement
new
也可以填充这些值;我假设它的意思大概是“分配”,但您的解释也起作用(特别是给定的,这可能意味着它可能以其他方式获得存储)。但是,根据该解释,placement
new
从中获取存储,这些存储都指定为“故意不执行其他操作”。更改
ptr
指向的字节将是一个“其他操作”。显然这是
std discussion
上的一个线程中对这一部分的常见解释,在那里它实际上正在被讨论,每个人都承认,一旦向您指出,placement
new
在这里不起作用,所以我的解释是错误的,我接受你的答案。至少当我在那里搜索的时候,我了解到了你自己和你自己的,希望这能让这个问题变得不那么重要。