这个问题是要确认我理解概念正确,并就使用方式和可能的优化采取专家意见。
我正在尝试理解“新的刊登位置”,以下是我想出的程序...
#include <iostream>
#include <new>
class A {
int *_a;
public:
A(int v) {std::cout<<"A c'tor clalled\n";_a= new int(v);}
~A() {std::cout<<"A d'tor clalled\n"; delete(_a);}
void testFunction() {std::cout<<"I am a test function &_a = "<<_a<<" a = "<<*_a<<"\n";}
};
int main()
{
A *obj1 = new A(21);
std::cout<<"Object allocated at "<<obj1<<std::endl;
obj1->~A();
std::cout<<"Object allocated at "<<obj1<<std::endl;
obj1->testFunction();
A *obj2 = new(obj1) A(22);
obj1->testFunction();
obj2->testFunction();
delete(obj1);// Is it really needed now? Here it will delete both objects.. so this is not the right place.
//obj1->testFunction();
//obj2->testFunction();
return 0;
}
当我运行该程序时,我会跟随o/p
A c'tor clalled
Object allocated at 0x7f83eb404c30
A d'tor clalled
Object allocated at 0x7f83eb404c30
I am a test function &_a = 0x7f83eb404c40 a = 21
A c'tor clalled
I am a test function &_a = 0x7f83eb404c40 a = 22
I am a test function &_a = 0x7f83eb404c40 a = 22
A d'tor clalled
I am a test function &_a = 0x7f83eb404c40 a = 0
I am a test function &_a = 0x7f83eb404c40 a = 0
我有以下问题...
还请指出您看到的任何我可以改进的地方,或者就是不要尝试。也欢迎任何好的引用或阅读。
最佳答案
这非常非常简单:new
可以看作是做两件事:
无法保证实现确实使用了
malloc
,但通常情况下确实如此。您不能假设它是关于实现的,但是出于理解的目的,这是一个好的假设。因此,以下内容被认为是等效的:
auto obj1 = new std::string("1");
// ↑ can be thought of as equivalent to ↓
auto obj2 = (std::string*)malloc(sizeof(std::string));
new(obj2) std::string("2");
delete
也是如此:delete obj1;
// ↑ can be thought of as equivalent to ↓
obj2->~string();
free(obj2);
然后,当您看到new
和delete
的真正含义时,可以很容易地对此进行推理:分配之后是构造函数调用,而析构函数调用之后是释放。当您使用
new
放置时,您已经决定分别进行第一步。必须仍然以某种方式分配内存,您才可以完全控制内存的发生方式以及内存来自何处。因此,您必须分别跟踪两件事:
下面的代码演示了它们如何彼此独立:
#include <cstdlib>
#include <string>
#include <new>
using std::string;
int main() {
auto obj = (string*)malloc(sizeof(string)); // memory is allocated
new(obj) string("1"); // string("1") is constructed
obj->~string (); // string("1") is destructed
new(obj) string("2"); // string("2") is constructed
obj->~string (); // string("2") is destructed
free(obj); // memory is deallocated
}
如果对象的生存期超过了内存的生存期,则您的程序将具有UB。确保内存始终超过对象的生命周期。例如,这具有UB:void ub() {
alignas(string) char buf[sizeof(string)]; // memory is allocated
new(buf) string("1"); // string("1") is constructed
} // memory is deallocated but string("1") outlives the memory!
但这没关系:void ub() {
alignas(string) char buf[sizeof(string)]; // memory is allocated
new(buf) string("1"); // string("1") is constructed
buf->~string(); // string("1") is destructed
} // memory is deallocated
注意如何使用 alignas
正确对齐自动缓冲区。任意类型缺少alignas
都会导致UB。它可能看起来有效,但这只是在误导您。在某些特定类型中,不调用析构函数且未正确对齐内存不会导致UB,但是您永远都不应假设这种类型。调用析构函数并进行对齐,如果事实证明这是不必要的,则不会花费您任何费用-这种类型的代码不会生成任何额外的代码。
struct S {
char str[10];
}
关于c++ - C++放置新功能如何工作?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35087204/