我编写了以下代码作为关于函数模板和模板特化的练习。它是一个函数,用于计算vector
:
template <typename T>
int function(const std::vector<T> &vec, T val) {
int count = 0;
for(typename std::vector<T>::const_iterator it = vec.begin(); it != vec.end(); ++it)
if(*it == val)
++count;
return count;
}
template <>
int function(const std::vector<const char*> &vec, const char* val) {
int count = 0;
for(std::vector<const char*>::const_iterator it = vec.begin(); it != vec.end(); ++it) {
if (std::string(*it) == std::string(val))
++count;
}
return count;
}
我在专业化中编写了代码,因为我想知道单词中的每个字符是否与给定的文字相同。令我惊讶的是,如果我注释掉特化并让编译器实例化原始模板,它甚至可以用于const char数组:
int main() {
std::vector<const char*> cvec = {"hi", "hi", "hallo", "hej", "hej", "hi", "hej", "hej", "hej"};
std::cout << function(cvec, "hej") << std::endl;
}
怎么可能?
答案 0 :(得分:4)
我使用main函数中的代码来测试它,但令我惊讶的是,如果我注释掉了特化并让编译器实例化原始模板,它甚至可以用于const char数组(类型字符串字面量)!怎么可能呢?
标准没有规定包含相同字符序列的字符串文字必须存储在同一个内存位置,如§2.13.5/ 16所述:
评估字符串文字会产生具有静态存储持续时间的字符串文字对象,从上面指定的给定字符初始化。 是否所有字符串文字都是不同的(即存储在非重叠对象中)以及字符串文字的连续评估是否产生相同或不同的对象是未指定的
(强调我的)
但是允许这个实现,这就是这里发生的事情:每个文字字符串"hej"
都存储在同一个内存地址中,因此==
const char*
正在检查地址是否为相同而且屈服于真。
要“证明”这个,我们只需要看一下这个例子:
int main() {
std::vector<const char*> cvec = {"hi", "hi", "hallo", "hej", "hej", "hi", "hej", "hej", "hej"};
std::cout << function(cvec, "hej") << '\n';
}
由于向量中有5个文字5
,因此产生"hej"
。但是,如果我们在文字中添加另一个char
数组,并且具有相同的char
s,那么我们知道应该有不同的地址:
int main() {
std::string hej = "hej";
std::vector<const char*> cvec = {"hi", "hi", "hallo", "hej", "hej", "hi", "hej", "hej", "hej", hej.c_str()};
std::cout << function(cvec, "hej") << std::endl;
}
然后我们看到计数不会改变。