dav*_*uda 7 c++ constructor new-operator
我正在阅读 Shaffer 的 Data Structures and Algorithm Analysis in C++(可在https://people.cs.vt.edu/shaffer/Book/免费获得),因为我看到它使用模板,我正在尝试了解更多关于C++ 和 C++ 中的泛型编程。
当作者介绍链表时,他给出了一个使用自由列表的变体。(这是大约第 111 页,pdf 第 130 页)。在他的实现中,他为 a 创建了一个类Link并覆盖operator new以从空闲列表中提取。然后有一个班级LinkedList。
然而,事实证明,在这个实现中,调用new LinkedList会导致构造函数被同一个对象调用两次,我很难弄清楚为什么。
此代码显示了示例的相关部分。
#include <cstddef>
#include <iostream>
struct S {
S() { std::cout << "ctor at " << this << "\n"; }
~S() { std::cout << "dtor at " << this << "\n"; }
};
class Link {
private:
static Link * freelist;
S elem;
Link * next;
public:
void * operator new(size_t) {
if (freelist == nullptr) { return ::new Link; }
Link * tmp = freelist;
freelist = freelist->next;
return tmp;
}
// other logic
};
Link * Link::freelist = nullptr;
class LinkedList {
private:
Link * head;
public:
LinkedList() { head = new Link; }
// other logic
};
int main() { LinkedList ll; }
Run Code Online (Sandbox Code Playgroud)
此代码的示例输出是
ctor at 0x458bbd954eb0
ctor at 0x458bbd954eb0
Run Code Online (Sandbox Code Playgroud)
所以我们可以看到结构的构造函数S被同一个对象调用了两次。
这是我所期望的。
main,我们构造了一个LinkedList.new Link. 我相信这会调用Link::operator new,我们已经覆盖了它。Link::operator new,我们看到Link看到其空闲列表为空,因此调用::new Link。::new Link构造一个Link,包括它的私有成员变量S elem,构造一个Sstruct。显然这是不正确的。我敢打赌,我错过new了编译器中的一个隐式--- 但即便如此,我还是很惊讶单个S实例的构造函数被调用了两次。所以我的心智模型肯定是不完整的。
你能帮助解释为什么构造函数在内存中的同一位置被调用两次吗?
operator new的任务是分配内存;它不能调用构造函数。operator new返回后自动调用构造函数。
因此,您的实现应如下所示:
void * operator new(size_t size) {
if (freelist == nullptr) {
// here is the difference:
return ::operator new(size);
}
Link * tmp = freelist;
freelist = freelist->next;
return tmp;
}
Run Code Online (Sandbox Code Playgroud)
在您的实现中,构造函数是从 调用的::new Link,然后在返回指针后,它会像往常一样在同一地址上再次调用。
当然,您应该实现互补的operator delete. 这个不能调用析构函数(已经被调用了),而只是将内存放入freelist.