C++11 通过函数访问全局变量-跨命名空间的不同实例

C++11 通过函数访问全局变量-跨命名空间的不同实例,c++11,namespaces,global-variables,C++11,Namespaces,Global Variables,我正在做一项大学作业。一般的想法是用C++编写一个库,并在C和C++头中公开它的内容。我们应该有一个全局变量,其中包含存储电话号码更改的字典字典(无序的_映射),并使用标题中公开的函数对其进行修改。换句话说,我们有无序的地图。这是我的C++头< /p> namespace jnp1 { extern "C" { extern size_t TEL_NUM_MAX_LEN; unsigned long maptel_create(); // create a dictionary of tel

我正在做一项大学作业。一般的想法是用C++编写一个库,并在C和C++头中公开它的内容。我们应该有一个全局变量,其中包含存储电话号码更改的字典字典(无序的_映射),并使用标题中公开的函数对其进行修改。换句话说,我们有
无序的地图
。这是我的C++头< /p>
namespace jnp1 {

extern "C" {
extern size_t TEL_NUM_MAX_LEN;

unsigned long maptel_create();
// create a dictionary of telephone number changes (old->new) and return its ID

void maptel_delete(unsigned long id);
// delete the dictionary ID

void maptel_insert(unsigned long id, char const *tel_src, char const *tel_dst);
// insert change into dictionary ID

void maptel_erase(unsigned long id, char const *tel_src);
// erase change from dictionary ID

void maptel_transform(unsigned long id, char const *tel_src, char *tel_dst, size_t len);
// follow chain of changes (nr1 -> nr2 -> ... -> final_number) and return final number
}
}
我们有一个类似的C头。 我们的库必须符合外部测试-C版本:

#include <assert.h>
#include <string.h>
#include "maptel.h" // our library C header

static const char t112[] = "112";
static const char t997[] = "997";

int main() {
  unsigned long id;
  char tel[TEL_NUM_MAX_LEN + 1]; /* +1 for terminal zero */

  id = maptel_create();
  maptel_insert(id, t112, t997);
  maptel_transform(id, t112, tel, TEL_NUM_MAX_LEN + 1);
  assert(strcmp(tel, t997) == 0);
return 0;
堆:

#包括“cmaptel”
typedef std::无序地图电话簿;
std::无序地图*书籍;
无符号长id_计数器;
外部“C”{
大小电话号码最大长度=22;
无符号长jnp1::maptel_create()
{
如果(books==NULL)books=new std::unordered_map();
(*books)[id_counter]=电话簿();
返回id_计数器++;
}
void jnp1::maptel\u erase(无符号长id,字符常量*tel\u src)
{
断言(书籍->计数(id));
std::字符串src(tel_src);
int result=(*books)[id].erase(src);
}
}

未跨多个翻译单元指定全局语言的初始化顺序。问题是
id
(因此对
maptel\u insert
的调用)在
书籍
之前被初始化。由于
maptel\u insert
在未初始化的对象上操作,因此这是未定义的行为

您已经找到了一种解决方法:按需动态分配地图,从而确保在使用前得到分配。另一个细微的变化是使用函数作用域静态,因为这些规则保证在使用之前对其进行初始化:

std::unordered_map<unsigned long, tel_book>& books()
{
    static std::unordered_map<unsigned long, tel_book> instance;
    return instance;
}
std::无序的地图和书籍()
{
静态std::无序的_映射实例;
返回实例;
}

非常感谢,这解决了我的问题。
#include "cmaptel"

typedef std::unordered_map<std::string, std::string> tel_book;
std::unordered_map<unsigned long, tel_book> books;

unsigned long id_counter;

extern "C" {
    size_t TEL_NUM_MAX_LEN = 22;

    unsigned long jnp1::maptel_create()
    {
        books.reserve(1);
        // without this for some reason we would get float arithmetic exception right here

        books[id_counter] = tel_book();
        return id_counter++;
    }

    void jnp1::maptel_erase(unsigned long id, char const *tel_src)
    {
        assert(books.count(id)); // this is the assertion that breaks
        std::string src(tel_src);
        int result = books[id].erase(src);

    }
}
#include "cmaptel"

typedef std::unordered_map<std::string, std::string> tel_book;
std::unordered_map<unsigned long, tel_book> *books;

unsigned long id_counter;

extern "C" {
    size_t TEL_NUM_MAX_LEN = 22;

    unsigned long jnp1::maptel_create()
    {
        if (books == NULL) books = new std::unordered_map<unsigned long, tel_book>();
        (*books)[id_counter] = tel_book();
        return id_counter++;
    }

    void jnp1::maptel_erase(unsigned long id, char const *tel_src)
    {
        assert(books->count(id));
        std::string src(tel_src);
        int result = (*books)[id].erase(src);

    }
}
std::unordered_map<unsigned long, tel_book>& books()
{
    static std::unordered_map<unsigned long, tel_book> instance;
    return instance;
}