这是代码的本质:
class DM
{
public:
int something;
DM() : something(0) { }
};
typedef DM * dm_t;
typedef dm_t & dm_ref_t;
typedef const DM * dm_const_t;
typedef dm_const_t & dm_cref_t;
int getSomething( dm_cref_t dm ) // CALLING getSomething DOES NOT COMPILE
{
return dm->something;
}
int getSomethingAgain( dm_const_t dm )
{
return dm->something;
}
int getSomethingOnceMore( dm_ref_t dm )
{
return dm->something;
}
int main()
{
dm_t dm = new DM;
getSomething( dm ); // COMPILER ERROR COMES FROM HERE
getSomethingAgain( dm );
getSomethingOnceMore( dm );
return 0;
}
这是编译器错误:
implicit_cast.cpp: In function ‘int main()’:
implicit_cast.cpp:31: error: invalid initialization of reference of type ‘const DM*&’ from expression of type ‘DM*’
implicit_cast.cpp:13: error: in passing argument 1 of ‘int getSomething(const DM*&)’
也就是说,我有一个非常量指针,我希望将其传递给一个通过引用接受const指针的函数。如果函数通过引用接受非常量指针或按值接受const指针,则一切都很好,但是const引用指针不接受非常量指针。
出于安全考虑,我喜欢使用const指针的功能;出于一些进一步的发展原因,我希望通过引用传递它。从非const到const自动转换应该是完全安全的。为什么没有g ++执行演员表?
我想进一步使用像getSomething这样定义的函数。如果我每次调用它而不添加显式强制转换,我如何合法化这些调用?
答案 0 :(得分:4)
它没有这样做,因为在扩展typedef后,你有
int getSomething( DM const* & dm )
{
return dm->something;
}
...
int main()
{
DM* dm = new DM;
getSomething( dm );
}
g ++正确地不允许这样做,因为你要求对常量指针进行非常量左值引用。您目前有一个非常量指针。它不能创建临时的,因为临时不能绑定到非const左值引用。
现在,如果您通过常量引用获取指针,它将起作用,因为它将被允许绑定到临时。但是,我只是直接传递指针,因为通过常量引用传递指针没有值。
这是不允许的原因是因为如果是这样的话,那么(违背const
系统的目的)
const int i = 5;
void foo( const int* & p)
{
p = &i;
}
void bar()
{
int * p;
foo(p); // Normally not legal
*p = 6; // And this is why
}
现在,所有这一切,只要我看到对指针的引用,我向开发人员提出的第一个问题就是为什么他们需要这样做。有时,它是因为你需要一个输出参数,但它不是我希望普及的东西。
答案 1 :(得分:2)
在C ++ 11标准中查看[conv.qual]
(4.4 / 4):
转换可以在第一个以外的级别添加cv限定符 多级指针,遵循以下规则:... [注意:如果是 程序可以将类型为T **的指针分配给const类型的指针 T **(即,如果允许下面的第1行),程序可以 无意中修改了一个const对象(就像它在第2行上所做的那样)。
给出的例子是:
int main() {
const char c = ’c’;
char* pc;
const char** pcc = &pc; // #1: not allowed
*pcc = &c;
*pc = ’C’; // #2: modifies a const object
}
这是针对指针的指针解释的,但出于完全相同的原因,同样适用于对指针的引用。
答案 2 :(得分:1)
这更像是C ++名称“resolution”。在你的情况下,你有一个指向const DM
的指针,但你想要一个const指针,所以你必须使用typedef dm_const_t const & dm_cref_t
(对const指针的const引用)
提供更多详情:
当您声明const int * a
时,您说a
是一个指向整数的常量指针。它与int const * a
相同。
如果要引用类型,则声明int & b
,这意味着b
是对整数的引用。以同样的方式思考,const int & c
与int const & c
相同(const总是限定变量,而不是类型)。
所以,如果你想要一个对const指针的const引用,那么使用第二种表示法会更清楚(如果不使用typedef
s则唯一可能的那样):int const * const & d
,意思是{{1} }是对整数的常量指针的常量引用。使用typedef:
d
答案 3 :(得分:0)
你不能。
你正在通过指针传递,这意味着在执行函数之后,可能存在对同一内存的两个不同引用,一个声明为const,一个声明为非const。
如果非const引用用于更改内存,那么const引用突然会使其底层内存突然改变,这将是不正确的行为。