有时在我的C++项目中使用pure-C库,我会看到奇怪的(在我看来(函数声明。
例如:libldap的ldap_search_ext((:https://linux.die.net/man/3/ldap_search_ext_s
int ldap_search_ext(
LDAP *ld,
char *base,
int scope,
char *filter,
char *attrs[], // this one!
int attrsonly,
LDAPControl **serverctrls,
LDAPControl **clientctrls,
struct timeval *timeout,
int sizelimit,
int *msgidp );
为什么attrs[]不能是const char *
?
像这样的声明不想改变指针的内容并产生很多问题:
// pure C
void func(char * data[])
{
...
}
func({"blabla"}); // won't work (corrected: yes, this is wrong syntax, but it's true for structs of pointers)
const char *d[] = {"blabla", "blablu"};
func(d); // won't work
// C++
const std::string str("blabla");
char * data[] = { str.data() }; // even non-const won't work (because data() returns const*)
/// etc...
有没有理由不将这些参数声明为const?
这主要是(由于(C标准中从未修复的历史缺陷。
当将const
添加到C中时,添加了隐式(安全(转换简单指针的能力——您可以将T *
隐式转换为const T *
。但是,更复杂的指针类型的(安全(转换被遗漏了——您无法将T * const *
转换为const T * const *
。因此,当库采用这样的双指针时,如果它是只读的,它就没有任何"好"的方法使其成为const
。将其设为const char **
或const char * const *
会破坏某些用途(需要混乱的显式强制转换(。
请注意,允许T **
到const T **
的隐式转换是不安全的——这样的指针可以用来修改T *
,使其指向不带强制转换的const T *
。
const
。
因此,在许多本应存在的图书馆中,历史上缺乏常量正确性。如果字符串常量是const
,程序员就会被迫对其进行解释
当处理这样的库时,您知道这些库不会修改参数,您必须应用const_cast
使其适合。
char *d[] = {const_cast<char *>("blabla"), const_cast<char *>("blablu")};
func(d);
const std::string str("blabla");
char * data[] = { const_cast<char *>(str.data()) };
func(data);