最近我碰到了C++的Singleton设计模式的实现/实现.看起来像这样(我从现实生活中采用了它):
// a lot of methods are omitted here
class Singleton
{
public:
static Singleton* getInstance( );
~Singleton( );
private:
Singleton( );
static Singleton* instance;
};
Run Code Online (Sandbox Code Playgroud)
从这个声明我可以推断出实例字段是在堆上启动的.这意味着存在内存分配.对我来说完全不清楚的是,什么时候内存将被解除分配?还是有漏洞和内存泄漏?好像在实施中存在问题.
我的主要问题是,如何以正确的方式实施它?
似乎没有简单的答案,但是有没有可以安全地做出关于何时可以访问静态类字段的假设?
编辑:唯一安全的假设似乎是所有静态都在程序开始之前初始化(调用main).那么,只要我不参考其他静态初始化代码中的静态,我就没有什么可担心的了?
我可以控制静态对象被破坏的顺序吗?有没有办法强制执行我想要的订单?例如,以某种方式指定我想要最后销毁某个对象,或者至少在另一个静态对象之后销毁?
在C++我知道static和global对象之前构造main函数.但是如你所知,之前C没有这种类型.initialization proceduremain
例如,在我的代码中:
int global_int1 = 5;
int global_int2;
static int static_int1 = 4;
static int static_int2;
Run Code Online (Sandbox Code Playgroud)
5和4存储的位置?初始化时如何管理它们?编辑:
澄清第二个问题.
5来初始化 global_int1,这样怎么能编译器分配 5到global_int?例如,编译器可能首先将5值存储在某处(即表),并在初始化开始时获取此值.constinit是P1143中提出的C ++ 20中的新关键字和说明符。
标准中提供了以下示例:
const char * g() { return "dynamic initialization"; }
constexpr const char * f(bool p) { return p ? "constant initializer" : g(); }
constinit const char * c = f(true); // OK
constinit const char * d = f(false); // ill-formed
Run Code Online (Sandbox Code Playgroud)
我想到了几个问题:
什么constinit意思 为什么要引入?在什么情况下我们应该使用它?
它使变量不可变吗?是暗示const还是constexpr?
变量可以是const和constinit吗?怎么样constexpr和constinit?
可以将说明符应用于哪些变量?为什么我们不能将其应用于static非thread_local变量?
有性能优势吗?
该问题旨在作为 …
我正在浏览http://geeksforgeeks.org/?p=10302上的代码
#include<stdio.h>
int initializer(void)
{
return 50;
}
int main()
{
static int i = initializer();
printf(" value of i = %d", i);
getchar();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
此代码不会在C中编译,因为静态变量需要在main()启动之前初始化.那样就好.但是这段代码在C++编译器中编译得很好.
我的问题是,当静态在两种语言中具有相同的用法时,为什么它在C++编译器中编译.当然编译器对于这些语言会有所不同,但我无法确定原因.如果在标准中指定,我很想知道.
我在SO上搜索了这个问题,找到了3个类似的链接但是徒劳无功. Link1 Link2 Link3
谢谢你的帮助.
我有一段代码结构如下:
a.cpp:
#include "b.hpp"
const unsigned a = create(1);
b.cpp:
map<int, string> something; // global variable
unsigned create(unsigned a){
something.insert(make_pair(a, "somestring"));
return a;
}
Run Code Online (Sandbox Code Playgroud)
现在,这引发了一个段错误,valgrind说地图尚未创建.它是如何工作的,我应该如何改变它?
在下面的最小示例中,通过LD_PRELOAD函数加载的库可以拦截fopen并且openat在初始化之前显然正在运行.(Linux是CentOS 7.3).为什么??
库文件comm.c:
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdarg.h>
#include <stdio.h>
#include <fcntl.h>
typedef FILE *(*fopen_type)(const char *, const char *);
// initialize to invalid value (non-NULL)
// init() should initialize this correctly
fopen_type g_orig_fopen = (fopen_type) 1;
typedef int (*openat_type)(int, const char *, int, ...);
openat_type g_orig_openat;
void init() {
g_orig_fopen = (fopen_type)dlsym(RTLD_NEXT,"fopen");
g_orig_openat = (openat_type)dlsym(RTLD_NEXT,"openat");
}
FILE *fopen(const char *filename, const char *mode) {
// have to do this here …Run Code Online (Sandbox Code Playgroud) 在我研究在C#中构建Singleton的最佳方法的过程中,我偶然发现了以下文章,其中简要提及在C++中
"C++规范在静态变量的初始化顺序方面留下了一些模糊性."
我最终寻找到这个问题,并发现这个和这个.基本上(据我所知),C++中静态变量的初始化顺序是未定义的.好吧,我想到目前为止这么好,但后来我想了解文章后面的说法
"幸运的是,.NET Framework通过处理变量初始化来解决这种歧义."
所以我发现他们说的这个页面
类的静态字段变量初始值设定项对应于以它们出现在类声明中的文本顺序执行的赋值序列.
并举例说明
using System;
class Test
{
static void Main() {
Console.WriteLine("{0} {1}", B.Y, A.X);
}
public static int F(string s) {
Console.WriteLine(s);
return 1;
}
}
class A
{
static A() {}
public static int X = Test.F("Init A");
}
class B
{
static B() {}
public static int Y = Test.F("Init B");
}
the output must be:
Init B
Init A
1 1
Run Code Online (Sandbox Code Playgroud)
"因为静态构造函数执行时的规则(如第10.11节所定义)规定B的静态构造函数(以及因此B的静态字段初始化程序)必须在A的静态构造函数和字段初始化程序之前运行." …
例如,node::node()以下代码段中的构造函数访问全局变量node::count而::tail没有任何多线程保护.C++标准是否保证输出始终是0 1 2(无论顺序如何)的排列?
#include <stdio.h>
struct node *tail;
struct node
{
static int count;
int index;
node *prev;
node()
{ index = count++; prev = tail; tail = this; }
};
int node::count;
node one, two[2];
int main(int argc, char *argv[])
{
for(node *p = tail; p; p = p->prev)
printf("%d\n", p->index);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我正在寻找基于(适用)标准的答案,而不是针对实现或编译器特定行为.有许多对SO有关的问题,但它不是完全清楚他们是如何直接适用于这个特定的和相当基本情况(是C++中的静态成员变量的初始化是线程安全的?,是本地静态变量的初始化线程安全的C++ 11 ?等).