C模板函数内的静态变量初始化

前端之家收集整理的这篇文章主要介绍了C模板函数内的静态变量初始化前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我注意到函数模板中静态变量初始化的一个奇怪的行为.请考虑以下示例:
  1. MyFile * createFile()
  2. {
  3. std::cout << "createFile" << std::endl;
  4. return nullptr;
  5. }
  6.  
  7. template <typename T>
  8. void test(const T& t)
  9. //void test(T t)
  10. {
  11. static MyFile *f = createFile();
  12. }
  13.  
  14. void main()
  15. {
  16. test("one");
  17. //test("two");
  18. test("three");
  19. }

只要测试中的f是静态的,我希望createFile只被调用一次.但是,它被调用两次.

花了一些时间来解决问题,我注意到从测试中的参数中删除const引用修复了它.另一个有趣的事情是传递给函数的字符串的长度也会影响初始化:当参数的长度相等时,静态变量只初始化一次,否则会发生新的初始化.

有人可以解释一下吗?除了上面提到的解决方案/解决方案之外,我们非常欢迎.

解决方法

文字“一”是一个const char [4].

这段代码

  1. test("one")

理想情况下会调用test(const char(&)[4])

这适用于测试(const T&)(因为const char(&)[4]可以绑定到const char(const&)[4]).

但它无法用于测试(T t),因为您无法按值传递字符串文字.它们通过引用传递.

但是,const char [4]可以衰减为const char *,它可以匹配模板< class T> void func(T t).

证据在于布丁:

  1. #include <cstdint>
  2. #include <iostream>
  3. #include <typeinfo>
  4.  
  5. template <typename T,std::size_t N>
  6. void test_const(const T(&t)[N])
  7. {
  8. std::cout << __func__ << " for literal " << t << " T is a " << typeid(T).name() << " and N is " << N << std::endl;
  9. }
  10.  
  11. template <typename T>
  12. void test_mutable(T &t)
  13. {
  14. std::cout << __func__ << " for literal " << t << " T is a " << typeid(T).name() << std::endl;
  15. }
  16.  
  17. template <typename T>
  18. void test_const_ref(const T &t)
  19. {
  20. std::cout << __func__ << " for literal " << t << " T is a " << typeid(T).name() << std::endl;
  21. }
  22.  
  23. template <typename T>
  24. void test_copy(T t)
  25. {
  26. std::cout << __func__ << " for literal " << t << " T is a " << typeid(T).name() << std::endl;
  27. }
  28.  
  29. int main()
  30. {
  31. test_const("one");
  32. test_const("three");
  33. test_mutable("one");
  34. test_mutable("three");
  35. test_const_ref("one");
  36. test_const_ref("three");
  37. test_copy("one");
  38. test_copy("three");
  39. }

示例结果(clang):

  1. test_const for literal one T is a c and N is 4
  2. test_const for literal three T is a c and N is 6
  3. test_mutable for literal one T is a A4_c
  4. test_mutable for literal three T is a A6_c
  5. test_const_ref for literal one T is a A4_c
  6. test_const_ref for literal three T is a A6_c
  7. test_copy for literal one T is a PKc
  8. test_copy for literal three T is a PKc

这是一个带有demangled名称的版本(将在clang和gcc上编译):

  1. #include <cstdint>
  2. #include <iostream>
  3. #include <typeinfo>
  4. #include <cstdlib>
  5. #include <cxxabi.h>
  6.  
  7. std::string demangle(const char* name)
  8. {
  9. int status = -1;
  10. // enable c++11 by passing the flag -std=c++11 to g++
  11. std::unique_ptr<char,void(*)(void*)> res {
  12. abi::__cxa_demangle(name,NULL,&status),std::free
  13. };
  14.  
  15. return (status==0) ? res.get() : name ;
  16. }
  17.  
  18. template <typename T,std::size_t N>
  19. void test_const(const T(&t)[N])
  20. {
  21. std::cout << __func__ << " for literal " << t << " T is a " << demangle(typeid(T).name()) << " and N is " << N << std::endl;
  22. }
  23.  
  24. template <typename T>
  25. void test_mutable(T &t)
  26. {
  27. std::cout << __func__ << " for literal " << t << " T is a " << demangle(typeid(T).name()) << std::endl;
  28. }
  29.  
  30. template <typename T>
  31. void test_const_ref(const T &t)
  32. {
  33. std::cout << __func__ << " for literal " << t << " T is a " << demangle(typeid(T).name()) << std::endl;
  34. }
  35.  
  36. template <typename T>
  37. void test_copy(T t)
  38. {
  39. std::cout << __func__ << " for literal " << t << " T is a " << demangle(typeid(T).name()) << std::endl;
  40. }
  41.  
  42. int main()
  43. {
  44. test_const("one");
  45. test_const("three");
  46. test_mutable("one");
  47. test_mutable("three");
  48. test_const_ref("one");
  49. test_const_ref("three");
  50. test_copy("one");
  51. test_copy("three");
  52. }

预期产量:

  1. test_const for literal one T is a char and N is 4
  2. test_const for literal three T is a char and N is 6
  3. test_mutable for literal one T is a char [4]
  4. test_mutable for literal three T is a char [6]
  5. test_const_ref for literal one T is a char [4]
  6. test_const_ref for literal three T is a char [6]
  7. test_copy for literal one T is a char const*
  8. test_copy for literal three T is a char const*

猜你在找的C&C++相关文章