C++17将包含std::byte
,一种用于一个原子可寻址内存单元的类型,在典型计算机上具有8位。
在这个标准化之前,当指向"原始"内存时,已经存在一点两难选择--一方面使用char*
/unsigned char*
,另一方面使用void *
。现在,首选void *
的原因之一被删除了--std::byte
与char
没有相同的含义;这是关于原始记忆,不是字符
所以,我的问题是:对于std::byte
的时代,关于什么时候比void *
更喜欢它,什么时候相反,有什么好的经验法则?
当然,当你处理旧代码或C代码时,你会受到它接受的内容的限制;我主要是指新代码,您可以选择所有类型。
4条答案
按热度按时间2guxujil1#
(This这是一个“潜在的”经验法则,它来自我的头顶,任何人都不会宽恕。)
经验法则:何时使用哪种指针?
*将
char *
用于文本字符序列,而不是其他任何内容。*在类型擦除场景中使用
void *
,即当指向的数据是类型化的,但由于某种原因不能使用类型化指针,或者不能确定它是否是类型化的。*使用
byte *
作为原始内存,没有任何迹象表明它持有任何类型化数据。上述情况的例外:
void *
/unsigned char *
/char *
;或者当非C代码强制您使用byte *
时,您仍然可以使用基于byte *
的接口 Package 这种用法,从而不会将这种情况暴露给C代码的其余部分。示例
void * my_custom_malloc(size_t size)
-错误byte * my_custom_malloc(size_t size)
-右侧struct buffer_t { byte* data; size_t length; my_type_t data_type; }
-错误struct buffer_t { void* data; size_t length; my_type_t data_type; }
-右侧cclgggtu2#
std::byte
的动机是什么?引自X1 E0 F1 X
许多程序需要面向字节的内存访问。今天,这类程序必须使用
char
、signed char
或unsigned char
类型来实现此目的。然而,这些类型执行“三重任务”。它们不仅用于字节寻址,还用作算术类型。角色的多样性为程序员的错误打开了大门--例如,意外地对应该被视为字节值的内存执行了算术运算--以及程序员和工具的困惑。从本质上讲,
std::byte
是用来“取代”char
类型的使用,当需要将原始内存作为字节来处理时,可以安全地Assert这在按值、按引用、指针和容器中使用时适用。std::byte
与char的含义不同;它是关于原始内存,而不是字符正确,所以在处理内存中的字节(例如,字节数组)时,
std::byte
应该优先于char
类型。对于
std::byte
的时代,关于什么时候比void *
更喜欢它,什么时候相反,有什么好的经验法则?我认为类似的指南现在也适用,当处理原始内存块时,需要字节寻址能力,
char *
等会比void *
更受欢迎,我认为同样的逻辑现在也适用,但是比char *
更受欢迎byte *
。char *
更适合字符序列。如果希望不透明地传递指针,
void *
可能仍然最适合这个问题。void *
本质上意味着“指向任何东西”,但任何东西仍然是东西,我们只是还没有说什么。此外,类型
uintptr_t
(和intptr_t
)可能会作为替代因素,当然这取决于所需的应用。...我主要是指新的代码,你可以选择所有的类型。
新的代码通常在兼容性之外(你不能选择类型)非常有限地使用
void *
。如果你需要基于字节的处理,那么推荐byte *
。blpfk2vs3#
首先,当您必须使用C库函数或一般来说使用任何其他
extern "C"
兼容函数时,void *
仍然有意义。接下来
std::byte
数组仍然允许单独访问它的任何元素。换句话说,这是法律的的:如果您希望能够允许这种低级别访问,例如,如果您希望手动复制全部或部分数组,则这是有意义的。
另一方面,
void *
实际上是一个 opaque 指针,从某种意义上说,在能够访问它的各个元素之前,您必须将它强制转换(转换为char
或byte
)。因此,我的观点是,只要您希望能够寻址数组元素或移动指针,就应该使用
std::byte
,并且void *
仍然有意义,它表示一个不透明的区域,该区域仅作为一个整体传递(实际上很难处理void *
)。但是
void *
的真实的用例在现代C中应该变得越来越不寻常,至少在高层,因为那些不透明区域通常应该隐藏在更高级别的类中,这些类带有处理它们的方法。因此,恕我直言,void *
最终应该限于C(和更老的C版本)兼容性和低级代码(如分配代码)。pjngdqdw4#
std::byte
不仅仅是"raw memory",它是字节可寻址的原始存储器 *,具有为其定义的逐位操作 *。您不应该盲目地使用
std::byte
来替换void*
。void*
保留其用途。void*
对处理代码来说意味着“这是一个数据块,但我不知道 * 这个数据是什么 *,也不知道 * 如何操作它 *。当您需要内存块的字节地址 * 并且只需要定义位操作 * 来操作该数据时,请使用
std::byte
。std::byte
没有没有定义常规的基本数学运算,如operator+
、operator-
或operator*
。没错,以下代码是非法的:换句话说,当
void*
不是 * 内容的处理代码 * 时,请使用void*
。标准::字节示例
就像我上面说的,你能在
std::byte
上做的就是像|
,&
和~
这样的位操作。下面是一个使用std::byte
的例子,注意你需要一个C17编译器来编译这个例子,有一个here,但是你必须从右上角的下拉列表中选择C17