C++模板静态成员实例化

发布于 2024-09-18 19:59:27 字数 687 浏览 9 评论 0原文

#include <map>
#include <iostream>
template <typename T>
class A 
{
 static std::map<int, int> data;
public:
 A()
 {
  std::cout << data.size() << std::endl;
  data[3] = 4;
 }
};

template <typename T>
std::map<int, int> A<T>::data;

//std::map<int, int> A<char>::data;

A<char> a;

int main()
{
 return 0;
}

这有什么问题吗?如果没有显式实例化,它会中断

 data[3] = 4; 
Explicit instantiation solves the problem but the program breaks after
std::cout << data.size() << std::endl;
what means that the static class template memeber data was instantiated.

#include <map>
#include <iostream>
template <typename T>
class A 
{
 static std::map<int, int> data;
public:
 A()
 {
  std::cout << data.size() << std::endl;
  data[3] = 4;
 }
};

template <typename T>
std::map<int, int> A<T>::data;

//std::map<int, int> A<char>::data;

A<char> a;

int main()
{
 return 0;
}

What is wrong with this? Without explicit instantiation it breaks at

 data[3] = 4; 

Explicit instantiation solves the problem but the program breaks after

std::cout << data.size() << std::endl;

what means that the static class template memeber data was instantiated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

东京女 2024-09-25 19:59:27

您的代码中没有显式实例化。

实例化的静态数据成员在其他静态数据成员之间没有初始化顺序。因此,您的代码实际上具有未定义的行为:根据编译器是否首先初始化映射或 a,对映射的引用是否有效。

请参阅 C++ 静态成员初始化

There is no explicit instantiation in your code.

There is no order of initialization of instantiated static data members among other static data members. So your code has effectively undefined behavior: Depending on whether the compiler first initializes the map or a, the reference to the map is valid or not.

See C++ Static member initialization.

夏至、离别 2024-09-25 19:59:27

我手边没有 Visual C++,但我可以看到使用 GCC 编译的代码也存在同样的问题。您需要初始化数据成员:

template<> std::map<int, int> A<char>::data = std::map<int, int>();

通过此更改,它可以正确编译并运行(对于我来说,在 Linux 上的 GCC 上)。

I don't have Visual C++ handy, but I can see the same problem with your code compiling with GCC. You need the initialize the data member:

template<> std::map<int, int> A<char>::data = std::map<int, int>();

With this change, it compiles and runs correctly (for me on GCC on Linux).

戴着白色围巾的女孩 2024-09-25 19:59:27

该代码中有几个错误。首先最初的想法并不好。您有两个全局静态对象:aA::data。它们初始化的顺序未定义。根据编译器的心情,您有 50% 的机会首先调用 a 的构造函数,并尝试将某些内容写入未初始化的 A::data 中。

这有时被称为静态初始化顺序失败问题。建议的解决方案是通过将此类对象移动到函数中将其转换为局部静态对象:

#include <map>
#include <iostream>

template <typename T>
class A
{
  std::map<int, int> &data()
  {
    static std::map<int, int> d;
    return d;
  }
public:
  A()
  {
    std::cout << data().size() << std::endl;
    data()[3] = 4;
  }
};

int main()
{
  A<char> a;
  return 0;
}

局部静态对象在第一次调用函数时初始化。

关于注释掉的“显式实例化”,您忘记了template <>

但在该行前面加上 template <> 前缀后,它仍然不是定义,而是一个声明。它声明在其他地方有 A::data 定义。要实际定义它,您需要用一些东西来初始化它,例如参见 Jack Lloyd 的回答。

There're several errors in that code. First the initial idea is not good. You have two global static objects: a and A::data. The order in which they're initialized is undefined. Depending on the mood of your compiler you have a 50% chance to have constructor of a called first and attempted to write something into non-initialized A::data.

This is sometimes called static init order fiasco problem. A suggested solution is to turn such objects into local static objects by moving them into functions:

#include <map>
#include <iostream>

template <typename T>
class A
{
  std::map<int, int> &data()
  {
    static std::map<int, int> d;
    return d;
  }
public:
  A()
  {
    std::cout << data().size() << std::endl;
    data()[3] = 4;
  }
};

int main()
{
  A<char> a;
  return 0;
}

Local static objects are initialized on first call to the function.

About the commented out "explicit instantiation" you forgot template <>.

But after you prefix that line with template <> it's still not definition but a declaration. It declares that there's A::data definition somewhere else. To actually define it you need to initialize it with something, see Jack Lloyd answer for example.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文