为什么C++没有直接对应于贴图新的贴片删除,即调用析构函数并调用适当的贴片删除操作符?
例如:
MyType *p = new(arena) MyType;
...
//current technique
p->~MyType();
operator delete(p, arena);
//proposed technique
delete(arena) p;
Run Code Online (Sandbox Code Playgroud) 在Andrei Alexandrescu关于错误处理的讨论中:
参见C++和2012年之后:Andrei Alexandrescu - C++中的系统错误处理(大约30分钟)
Andrei提供以下代码:
~Expected()
{
using std::exception_ptr;
if (gotHam) ham.~T();
else spam.~exception_ptr();
}
Run Code Online (Sandbox Code Playgroud)
这个析构函数正在清理一个union包含某种类型T或一个类型的析构函数std::exception_ptr.工会填充使用placement new.
然后安德烈解释说这using std::exception_ptr;是必要的,因为以下代码不解析:
else spam.~std::exception_ptr();
Run Code Online (Sandbox Code Playgroud)
这意味着如果需要在不同的命名空间中显式调用类的析构函数,则始终需要使用using指令.
为什么第二个例子不解析?
以下代码是否是有效的替代方案?
else delete spam;
Run Code Online (Sandbox Code Playgroud)
这是否与显式调用析构函数具有相同的效果 std::exception_ptr
我确信这段代码应该是非法的,因为它显然不会起作用,但它似乎被C++ 0x FCD所允许.
class X { /* ... */};
void* raw = malloc(sizeof (X));
X* p = new (raw) X(); // according to the standard, the RHS is a placement-new expression
::operator delete(p); // definitely wrong, per litb's answer
delete p; // legal? I hope not
Run Code Online (Sandbox Code Playgroud)
也许你们中的一位语言律师可以解释标准如何禁止这一点.
还有一个数组形式:
class X { /* ... */};
void* raw = malloc(sizeof (X));
X* p = new (raw) X[1]; // according to the standard, the RHS is a placement-new expression
::operator delete[](p); // definitely …Run Code Online (Sandbox Code Playgroud) 在他的新书TC++ PL4中, Stroustrup 对用户控制的内存分配和放置 - 或者更具体地说,关于神秘的"放置"的惯常做法 略有不同.在书的教派.11.2.4,Stroustrup写道:newdelete
delete除了可能通知垃圾收集器已删除的指针不再安全地派生之外,"placement "运算符不执行任何操作.
这意味着声音编程实践将通过调用放置delete来显式调用析构函数.
很公平.但是,没有更好的语法来调用放置而delete不是模糊
::operator delete(p);
Run Code Online (Sandbox Code Playgroud)
我问的原因是Stroustrup的教派.11.2.4没有提到这种奇怪的语法.事实上,Stroustrup没有详述此事; 他根本没有提到任何语法.我隐约不喜欢这样的外观::operator,它将命名空间解析的问题插入到与名称空间无关的内容中.不存在更优雅的语法吗?
作为参考,这里是Stroustrup在更全面的上下文中的引用:
默认情况下,operator
new在免费商店中创建其对象.如果我们想要在其他地方分配对象怎么办?...我们可以通过提供带有额外参数的allocator函数将对象放在任何地方,然后在使用时提供这样的额外参数new:Run Code Online (Sandbox Code Playgroud)void* operator new(size_t, void* p) { return p; } void buf = reinterpret_cast<void*>(0xF00F); X* p2 = new(buf) X;由于这种用法,
new(buf) X提供额外参数的语法operator new()称为放置语法. 请注意,每个都operator new()将大小作为其第一个参数,并且隐式提供分配的对象的大小.在operator new()由所使用的new操作者是由通常的说法,匹配规则选择; 每个operator new()都有一个size_t作为它的第一个参数."放置"
operator new()是最简单的这种分配器.它在标准标题中定义<new>: …
我有一个以这种方式描述的类:
class Foo {
int size;
int data[0];
public:
Foo(int _size, int* _data) : size(_size) {
for (int i = 0 ; i < size ; i++) {
data[i] = adapt(_data[i]);
}
}
// Other, uninteresting methods
}
Run Code Online (Sandbox Code Playgroud)
我无法改变那门课程的设计.
如何创建该类的实例?在调用构造函数之前,我必须保留足够的内存来存储其数据,因此它必须在堆上,而不是在堆栈上.我想我想要的东西
Foo* place = static_cast<Foo*>(malloc(sizeof(int) + sizeof(int) * size));
*place = new Foo(size, data); // I mean : "use the memory allocated in place to do your stuff !"
Run Code Online (Sandbox Code Playgroud)
但我找不到办法让它发挥作用.
编辑:正如评论员所注意到的,这不是一个非常好的整体设计(使用非标准技巧data[0]),唉这是一个我不得不使用的库...
如标题所述,这是我的代码:
class Foo {
public:
Foo (int charSize) {
str = new char[charSize];
}
~Foo () {
delete[] str;
}
private:
char * str;
};
Run Code Online (Sandbox Code Playgroud)
对于这个类,有什么区别:
int main () {
Foo* foo = new Foo(10);
delete foo;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
和
int main () {
Foo* foo = new Foo(10);
foo->~Foo();
return 0;
}
Run Code Online (Sandbox Code Playgroud) 本质上,如果我创建一个新类的多个实例,我是否需要为每个实例调用析构函数,或者一旦销毁每个实例就调用它(如果我使用含糊/错误的术语,我道歉,构造函数/析构函数是概念我还没完全掌握).
更具体地说,这是我正在使用的一些代码(如果样式不好,我将不得不再次道歉,我对学校问题有了一个想法,并希望快速得到代码).
while(read >> f >> l >> t >> s >> sta >> acct >> bal)
{
cout << "test" << endl;
ptr[i] = new account(f,l,t,s,sta,acct,bal);
ptr[i]->printcontents();
cout << "test" << endl;
i++;
cout << i << endl;
}
Run Code Online (Sandbox Code Playgroud)
所以为了这个问题,假设这个循环三次.我是否只需要调用"帐户"的析构函数来销毁所有三个新帐户实例,或者一个调用会离开另外两个?这甚至是一个好习惯吗?
编辑:我注意到我的一些帖子被切断,所以我添加了最后几行,但人们已经解决了这个问题.我是用户指针的原因纯粹是因为作业决定了我这样做; 坦率地说,我现在没有看到使用它们的重点,但我认为它们在某个地方变得有用.我还应该补充说,动态内存分配也应该在赋值中使用.
我正在创建一个结构,其中的字段是堆上的unordered_map.当我使用new时,我可以毫无问题地添加它.但是使用calloc,我得到一个插入错误,因为桶大小为0.我调用reserve后工作正常.
那么,当在结构上调用calloc时,unordered_map构造函数不会运行吗?我很困惑为什么如果它在一个新版本的结构中,它似乎具有非零桶大小.除了召唤预备队之外,还有更好的方法吗?(在这种情况下我不能使用删除,所以我需要坚持使用calloc调用)