1

我编写了以下代码作为关于函数模板和模板特化的练习。它是一个计算给定类型的对象在 a 中的数量的函数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;
}

Live demo

怎么可能?

4

1 回答 1

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';
}

Live demo

5是因为向量中有 5 个文字"hej"。但是如果我们在字面量中添加另一个char具有相同chars 的数组,我们知道它应该有一个不同的地址:

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;
}

Live demo

然后我们看到计数没有改变。

于 2015-08-31T21:51:27.167 回答