访问指针变量作为指向 C++ 中不同类型的指针 [英] Accessing pointer variable as a pointer to a different type in C++
问题描述
通过取消对指向不同类型或 void
的指针的指针的引用来访问指针变量是一种好习惯吗?这会打破严格的别名规则吗?C 和 C++ 在别名规则上有一些不同.在这个问题中,我们关注 C++.可以找到考虑 C 的另一个问题 这里.在下面的示例中,double*
被作为 void*
访问.
Is it good practice to access a pointer variable by dereferencing a pointer to a pointer, which points to a different type or void
? Could this break strict aliasing rules? C and C++ have some differences in aliasing rules. In this question we focus on C++. The other question considering C can be found here. In the following example a double*
is accessed as a void*
.
int create_buffer(void** ptr, ...)
{
*ptr = malloc(...);
...
}
int main(void)
{
double* buffer;
// The problematic code is here, double**
// is coerced to void**, which is later
// dereferenced by the function
create_buffer(reinterpret_cast<void**>(&buffer), ...);
...
}
如果这是导致 UB,那么以下情况呢?
If this is causes UB, what about the following?
// process A
int* p; ...
printf("%p", p); // UB?
// process B
int* p;
scanf("%p", &p); // UB?
这看起来像一个糟糕的例子,但如果两个进程通过管道相互通信,最终一个进程将一个指向全局分配内存的指针传递给另一个进程会怎样.
This looks like a bad example, but what if two processes talk to each other through pipes, and eventually one process passes a pointer to globally allocated memory to the other process.
推荐答案
访问...是个好习惯吗
Is it good practice to access...
没有.void*
不是 C++ 中多态和重用的首选类型,即使不考虑原始代码中的别名问题.借助丰富的模板机制,您可以使代码具有强类型并更安全地启动.明显的改进是使用模板和类型安全分配:
No. void*
is not the go to type for polymorphism and reuse in C++, even without considering the aliasing issues in your original code. With a rich template mechanism available you can make your code strongly typed and safer to boot. The obvious improvement is to use templates, and type safe allocation:
template<typename T>
int create_buffer(T** ptr, ...)
{
*ptr = new T[...];
...
}
但是说到切线,这仍然不是 C++ 的样子.好的 C++ 是关于正确管理复杂性.跟踪缓冲区是一项复杂的任务.好的 C++ 方法不是手工完成,而是将其封装在专用类(模板)中.事实上,这是一个很常见的任务,标准库提供了一个解决方案.
But to go off on a tangent, this is still not how good C++ will look like. Good C++ is about managing complexity correctly. And tracking a buffer is a complex task. The good C++ approach is to not do it by hand, but to encapsulate it in a dedicated class (template). In fact, this is such a common task, that the standard library provides a solution.
好的做法是使用 std::vector
而不是缓冲区创建函数.类型通用任务的类模板通常会击败任何 void*
的使用.这将完全避免任何别名问题,因为始终使用正确的类型.
The good practice is to use std::vector<double>
instead of the buffer creation function. A class template for a type generic task will often beat any use of void*
. That will avoid any aliasing issues entirely, since the correct type is always used.
这篇关于访问指针变量作为指向 C++ 中不同类型的指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!