C++易失性放置新

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)

它会编译,但会调用未定义的行为.

Bri*_*ian 8

我想说你可以这样做:

new (const_cast<SomeStruct*>(thing)) volatile SomeStruct(...);
Run Code Online (Sandbox Code Playgroud)

但我不确定这是否有效.问题在于,由于分配函数返回void*构造volatile SomeStruct对象的内容,因此对内存的访问可能不具有volatile语义,从而导致未定义的行为.

所以我不确定使用placement new将对象构造成一个volatile限定的内存块是否合法.但是,假设内存最初是一个非易失性数组char,这似乎是正确的解决方案.

  • 标准可能根本不包括这个,`volatile`限定符限定了对象,但是在构造函数完成之前对象不存在. (2认同)

Nia*_*all 7

我知道如果没有volatile关键字,这将有效......但我怎么能用volatile变量做到这一点?

放置new与在给定位置构建对象有关.cv-qualifiers仅在构造对象后应用.所述const-ness或volatile-ity只适用一旦对象被构造.从这个意义上说,放置new不提供接受volatile(或const)指针的重载是有道理的.从C++标准(草案)[class.ctor/3]这里 ;

构造函数可以被调用用于const,volatileconst volatile对象.constvolatile语义([dcl.type.cv])不适用于正在构建的对象.它们在最派生对象([intro.object])的构造函数结束时生效.

任何企图将volatile线索抛弃到未定义的行为,请参见此处的cppreference ;

const通过非const访问路径修改对象并volatile通过非volatileglvalue 引用对象会导致未定义的行为.

另见[expr.const.cast/6].

给定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)