依赖静态对象地址安全吗
Is it safe to rely on static object adresses?
假设我有这样的代码:
#include <iostream>
#include <unordered_map>
#include <functional>
using const_string_ref = std::reference_wrapper<const std::string>;
namespace std
{
template<>
struct hash<const_string_ref>
{
size_t operator()(const const_string_ref& ref) const
{
return std::hash<std::string>()(ref);
}
};
bool operator==(const const_string_ref& lhs,
const const_string_ref& rhs)
{
return (lhs.get() == rhs.get());
}
}
class test
{
public:
void process(const std::string& action)
{
(this->*(ACTIONS_PROCESSORS_MAP_.at(action)))();
}
private:
using action_processor = void (test::*)();
using actions_map = std::unordered_map<const_string_ref, action_processor>;
private:
static const std::string FIRST_KEY_;
static const std::string SECOND_KEY_;
static const actions_map ACTIONS_PROCESSORS_MAP_;
private:
void first_action()
{
std::cout << "first works" << std::endl;
}
void second_action()
{
std::cout << "second works" << std::endl;
}
};
const std::string test::FIRST_KEY_ = "first";
const std::string test::SECOND_KEY_ = "second";
const test::actions_map test::ACTIONS_PROCESSORS_MAP_ =
{{std::cref(FIRST_KEY_), &test::first_action},
{std::cref(SECOND_KEY_), &test::second_action}};
int main()
{
test t;
t.process("first");
t.process("second");
return 0;
}
主要问题是:
我是否保证在进入main
函数时,test::ACTIONS_PROCESSORS_MAP_
中用作密钥的reference_wrapper
中包含的引用将分别被正确初始化为对test::FIRST_KEY_
和test::SECOND_KEY_
的有效引用,而与静态顺序初始化无关?
这个问题可以概括为:
指向satatic对象的指针/引用是否在这些对象初始化之前就有效(即地址是否会在某个时刻更改)?
是的,一旦分配了对象的存储,即使尚未初始化,也可以安全地获取对象的地址。静态对象的存储在程序期间持续,因此您可以随时获取地址。
当然,在对象的生存期之外访问对象本身是不允许的。
值得一提的是,在单个翻译单元中对非局部静态变量(不在类模板数据成员中)的初始化是有序的(§3.6.2/2):
显式专用类模板静态数据成员的定义[…不是这个]。其他类模板静态数据成员[…不是这个]。其他具有静态存储持续时间的非本地变量已下令初始化。在单个翻译单元中定义的有序初始化变量应按照其在翻译单元中的定义顺序进行初始化。
因此,您知道FIRST_KEY_
将在SECOND_KEY_
之前初始化,ACTIONS_PROCESSORS_MAP_
将在之前初始化。
但即使不是这样,也没关系。由于std::string
具有非平凡的结构,因此从分配存储到开始使用寿命之间还有一段时间。在这个时候,有一个指向对象的指针是可以的,只要你不使用它做某些事情。你的代码不会对它做任何事情,而是存储指针-你是安全的。§3.8/5:
在对象的生存期开始之前,但在分配对象将占用的存储之后,或者在对象的生命期结束之后,在重用或释放对象所占用的存储之前,可以使用任何指向对象将要或曾经所在的存储位置的指针,但只能以有限的方式使用。
有限的方法基本上是不涉及访问对象的任何方法。事实上,甚至可以通过指针执行间接操作,只要它最终不会进行左值到右值的转换(本质上代表从内存中读取对象)。
- 从不同线程使用int64的不同字节安全吗
- 将数组的地址分配给变量并删除
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 空基优化子对象的地址
- C++ 指针的内存地址和指向数组的内存地址如何相同?
- 虚拟决赛作为安全
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- 如何将元素添加到数组的线程安全函数?
- 在C++中打印指向不同基元数据类型的指针的内存地址
- 如何在c++程序中找到函数的地址
- 向量元素的引用地址与它所指向的向量元素的地址不同.为什么
- C++中的线程安全删除
- 被解释为低级别const的const对象的地址
- 取临时地址是否安全
- 使用函数模板中静态局部变量的地址作为类型标识符是否安全
- 在Visual C 中找到调用函数地址(安全)
- 依赖静态对象地址安全吗
- 在移动之前获取右值引用的地址被认为是安全的
- 访问数组C++的最后一个地址的最安全方法
- 按地址访问std::array数据是否安全?