c++引用与const指针带来的坑
起源
- 一个平平无奇的模板函数
- 接收两个参数: 类型为
T的const引用,一个同样参数的回调函数 - 直接将第一个参数传入回调
1
2
3
4
5template<typename T>
void foo(const T & data, const std::function<void(const T &)> & callback)
{
callback(data);
} - 代码看起来没有什么问题,使用一下
1
2
3
4
5
6
7
8int main()
{
int a = 1;
int* ptr = &a;
foo<int> (a, [](const int & data){ std::cout << data << std::endl; });
foo<int*>(ptr, [](const int* & data){ std::cout << *data << std::endl; });
return 0;
} - 使用g++编译,第一个
T为int的foo调用没有问题,但T为int*编译器会报错:找不到匹配的函数 - 初一看就很奇怪了
const引用与const指针
- 仔细分析下所谓
const引用就是意味着变量不能被修改为其他值 - 那么
const引用的指针也即指针不能修改为其他值,即不能指向别的区域 - 这里就和
void* const这样的指针等价了 - 所以这里编译器应该是针对指针进行了语义转换(或者说内部引用的实现就是通过指针完成的)
- 这样就可以理解了,模板参数
int*会被当做int*const,也就导致我们参数不一致编译失败 - 如此,修改起来就简单了,把
int*改为int*const即可1
2
3
4
5
6
7
8int main()
{
int a = 1;
int* ptr = &a;
foo<int> (a, [](const int & data){ std::cout << data << std::endl; });
foo<int*const>(ptr, [](const int* const & data){ std::cout << *data << std::endl; });
return 0;
}
没有const的引用就是普通的指针
- 进一步验证,把
foo对T的引用不使用const - 此时模板参数就可以为
int*了以上1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22template<typename T>
void foo(const T & data, const std::function<void(const T &)> & cb)
{
cb(data);
}
template<typename T>
void foo2(T & data, const std::function<void(T &)> & cb)
{
cb(data);
}
int main()
{
int a = 1;
int* ptr = &a;
foo<int>(a, [](const int & data){ std::cout << data << std::endl; });
foo<int*const>(ptr, [](const int* const & data){ std::cout << *data << std::endl; });
foo2<int*>(ptr, [](int* & data){ std::cout << *data << std::endl; });
return 0;
}