以下代码:
typedef void* ptr_t;
void func()
{
const ptr_t ptr; // Line 1
ptr = ...; // Line 2
}
产生以下编译错误:
第1行,错误C2734(C ++):const
对象必须初始化,如果不是extern
第2行,错误C3892(C ++):您无法分配给const
第2行,错误C2166(C):l值指定const
对象
这些编译错误背后的原因:
const ptr_t ptr
被解释为void* const ptr
而不是const void* ptr
使用void* const ptr
,您无法更改指针,但可以更改指向数据
使用const void* ptr
,您可以更改指针,但无法更改指向数据
我的目标是防止可能尝试更改ptr
指向的内存内容。
我可以使用#define ptr_t void*
代替typedef void* ptr_t
解决此问题。
但就编码正确性而言,它并不是一个合适的解决方案。还有其他选择吗?
由于
答案 0 :(得分:4)
这是一个将指针指向对象转换为指向const对象的指针的C ++解决方案:
#include <type_traits>
template <typename T>
using more_const_ptr = typename std::enable_if<
std::is_pointer<T>::value,
typename std::add_pointer<
typename std::add_const<
typename std::remove_pointer<T>::type>::type>::type>::type;
用法:
using p = int *; // or "typedef int * p;" in C++03
int a = 10;
more_const_ptr<p> q = &a;
// *q = 20; // Error, q is "const int *"
(在C ++ 14中,有一些有用的快捷方式可以让它更具可读性:)
template <typename T>
using more_const_ptr = std::enable_if_t<
std::is_pointer<T>::value,
std::add_pointer_t<std::add_const_t<std::remove_pointer_t<T>>>>;
答案 1 :(得分:3)
在第1行中,正如你所说,你有一个指针类型,然后使它成为const。这意味着您有一个指向(非常量)数据的常量指针。将其声明为type const
不会解决任何问题,因为C指定此声明等同于const type
。
没有解决方法。通常,在typedef下隐藏指针是个坏主意。这使得代码非常难以阅读,即使您有可变命名的编码标准。只需查看Windows API,即可获得如何将C语言转换为可读性较低的完美示例。
所以快速&amp;肮脏的解决方案是通过声明typedef const void* cptr_t;
来深入挖洞。或者确实使用宏,这是一个同样糟糕的解决方案。
好的解决方案是忘记隐藏在typedef背后的指针和其他将公知的C或C ++语言改为某种神秘的个人宏语言的尝试。
答案 2 :(得分:3)
#include <type_traits>
...
typedef std::remove_pointer<ptr_t>::type base_type;
typedef base_type const* const_ptr_t;
如果ptr_t
实际上是模板参数而不是具体类型,那么您需要在其中抛出typename
:
typedef typename std::remove_pointer<ptr_t>::type base_type;