Dar*_*bik 17 c++ volatile placement-new
如何在易失性指针上执行放置新操作.
例如,我想做这样的事情:
volatile SomeStruct Object;
volatile SomeStruct* thing = &Object;
new (thing) SomeStruct(/*arguments to SomeStruct's constructor*/);
Run Code Online (Sandbox Code Playgroud)
我知道如果没有volatile关键字,这会有用......但是如何使用volatile变量呢?
注意:
Placement new定义如下:
void* operator new(size_t memoryRequested, void* pointer)
{
return pointer;
}
Run Code Online (Sandbox Code Playgroud)
(顺便说一句,这是GCC如何实现它):
// Default placement versions of operator new.
inline void* operator new(std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT
{ return __p; }
Run Code Online (Sandbox Code Playgroud)
问题是我试图将thing
类型转换volatile SomeStruct*
为void*
,这是不允许的.
例如,如果我将new运算符更改为:
void* operator new(size_t memoryRequested, volatile void* pointer)
{
return (void*)pointer;
}
Run Code Online (Sandbox Code Playgroud)
它会编译,但会调用未定义的行为.
我想说你可以这样做:
new (const_cast<SomeStruct*>(thing)) volatile SomeStruct(...);
Run Code Online (Sandbox Code Playgroud)
但我不确定这是否有效.问题在于,由于分配函数返回void*
构造volatile SomeStruct
对象的内容,因此对内存的访问可能不具有volatile语义,从而导致未定义的行为.
所以我不确定使用placement new将对象构造成一个volatile限定的内存块是否合法.但是,假设内存最初是一个非易失性数组char
,这似乎是正确的解决方案.
我知道如果没有
volatile
关键字,这将有效......但我怎么能用volatile
变量做到这一点?
放置new
与在给定位置构建对象有关.cv-qualifiers仅在构造对象后应用.所述const
-ness或volatile
-ity只适用一旦对象被构造.从这个意义上说,放置new
不提供接受volatile
(或const
)指针的重载是有道理的.从C++标准(草案)[class.ctor/3]这里 ;
构造函数可以被调用用于
const
,volatile
或const volatile
对象.const
和volatile
语义([dcl.type.cv])不适用于正在构建的对象.它们在最派生对象([intro.object])的构造函数结束时生效.
任何企图将volatile
线索抛弃到未定义的行为,请参见此处的cppreference ;
const
通过非const
访问路径修改对象并volatile
通过非volatile
glvalue 引用对象会导致未定义的行为.
给定volatile
和放置的使用,new
问题中的断言(和一些注释)是该对象需要与信号处理程序一起使用并映射到内存中的特定位置.
虽然有一些替代方案......
如果不需要特定位置,最好不要使用放置new
,只需volatile
在对象声明的位置添加一个限定符;
struct SomeStruct {
/*...*/
};
// ...
volatile SomeStruct Object;
Run Code Online (Sandbox Code Playgroud)
如果需要放置new
和放置volatile
,则重新排序它们的使用.根据需要构造对象,然后添加限定符;
SomeStruct Object;
// ...
void* p = &Object; // or at the required location
volatile SomeStruct* p2 = new (p) SomeStruct;
Run Code Online (Sandbox Code Playgroud)
它struct
必须是不稳定的吗?所述volatile
的部分struct
可以被内化/抽象和cv修饰符数据将不需要被暴露给客户端,首先,它是内部处理的struct
;
struct SomeStruct {
volatile int data;
void DoSomething()
{
data = 42;
}
};
SomeStruct Object;
/* ... */
void* p = &Object;
auto p2 = new (p) SomeStruct{};
p2->DoSomething();
Run Code Online (Sandbox Code Playgroud)
内部化易失性对象的初始化,另一种方法是允许根据需要SomeStruct
进行惰性初始化(或重新初始化/重置).鉴于一些明显的限制,这可能不太可行.
struct SomeStruct {
void Initialise() volatile
{
/*...*/
}
}
Run Code Online (Sandbox Code Playgroud)