C++11 通过函数访问全局变量-跨命名空间的不同实例
我正在做一项大学作业。一般的想法是用C++编写一个库,并在C和C++头中公开它的内容。我们应该有一个全局变量,其中包含存储电话号码更改的字典字典(无序的_映射),并使用标题中公开的函数对其进行修改。换句话说,我们有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++头< /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;
}