C++ 实现C+的高效初始化+;模板列表类

C++ 实现C+的高效初始化+;模板列表类,c++,templates,C++,Templates,为了编写一个模板列表类,相当于vector(纯粹作为一个设计练习),我试图找出如何提高效率 如果有人写道: v = new T[size]; 然后编译器将调用T的构造函数,对吗T() 因此,在下面的课程中: v = (T*) new char[sizeof(T) * size] 这似乎很容易。但是,在析构函数中,如何仅删除已初始化的析构函数?在下面的类中,只初始化第一个“已使用”的元素 另外,在复制构造函数中,如何高效地仅为使用的元素调用T的复制构造函数 如果我以昂贵的方式初始化,它可以工作

为了编写一个模板列表类,相当于vector(纯粹作为一个设计练习),我试图找出如何提高效率

如果有人写道:

v = new T[size];
然后编译器将调用
T
的构造函数,对吗
T()

因此,在下面的课程中:

v = (T*) new char[sizeof(T) * size]
这似乎很容易。但是,在析构函数中,如何仅删除已初始化的析构函数?在下面的类中,只初始化第一个“已使用”的元素

另外,在复制构造函数中,如何高效地仅为使用的元素调用
T
的复制构造函数

如果我以昂贵的方式初始化,它可以工作:

v = new T[size];
for (int i = 0; i < used; i++)
  v[i] = orig.v[i];

首先,只需使用
std::vector
,而不是自己重新实现

这里要查找的是新的显式析构函数调用。通常情况下,每个
new
应与
delete
配对,每个新位置应与显式析构函数调用配对

要回答您的具体问题:

但是,在析构函数中,如何仅删除已初始化的析构函数

显式调用它们的析构函数,然后正确地
delete[]
原始
char[]
分配,这将(正确地)不会自动调用任何
T
析构函数

for (uint32_t i = 0; i < used; ++i) {
    v[i]->~T();
}

delete [] reinterpret_cast<char *>(v);
#include <new>

~List() {
    while (used) {
        --used;
        v[used]->~T();
    }
    delete[] reinterpret_cast<char*>(v);
}

List(const List& orig) : used(orig.used), capacity(orig.capacity),
    v(reinterpret_cast<T*>(new char[sizeof(T)*capacity])) {
    // now copy only the used ones
    for (int i = 0; i < used; i++)
        new(v+i) T(orig.v[i]);
}

与std::vector类似,您需要使用“placement new”并显式调用析构函数

for (uint32_t i = 0; i < used; ++i) {
    v[i]->~T();
}

delete [] reinterpret_cast<char *>(v);
#include <new>

~List() {
    while (used) {
        --used;
        v[used]->~T();
    }
    delete[] reinterpret_cast<char*>(v);
}

List(const List& orig) : used(orig.used), capacity(orig.capacity),
    v(reinterpret_cast<T*>(new char[sizeof(T)*capacity])) {
    // now copy only the used ones
    for (int i = 0; i < used; i++)
        new(v+i) T(orig.v[i]);
}
#包括
~List(){
while(已使用){
--使用;
v[used]->~T();
}
删除[]重新解释(v);
}
列表(常数列表和原始):使用(原始使用)、容量(原始容量),
v(重新解释铸造(新字符[sizeof(T)*容量]){
//现在只复制用过的
for(int i=0;i

注意,上面的复制构造函数不是异常安全的。尝试这样做。

在复制构造函数中,您可以尝试以下代码:

#包括


你对阵列有强烈的吸引力吗?您可以使用
向量
+
保留
定位
。。。当然,为初始化提供适当的构造函数。使用向量只会解决这个问题。这个类试图成为类向量,所以我想知道如何使它工作。对不起,我没有抓住要点。我想我得睡觉了。没有办法手动复制单个元素吗?比如调用析构函数?我在想从原点到向量的每个物体的某种省略副本。我不知道你在问什么<代码>新(v+i)T(原v[i])
复制单个元素。
::new((void*(v+i))
@aschepter。placement new如何分配容量元素,并仅使用其中的一个进行初始化?我会遇到同样的问题。我看不到如何在使用的对象上触发构造函数。placement new不分配内存,它直接调用构造函数。
::new((void*)(v+i))
No,例如,如果T包含指针,则此行为不正确。如果
[T=int*]
对于上述解决方案,只需创建一个新对象并仅复制地址。如果我们将每个元素的值复制到一个新对象,这将变得不可能。我们不知道每个元素的长度,因为我们不知道每个元素使用new
int()
new int[capacity]
初始化。如果
[T=List*]
这是可能的,但我需要修复上述解决方案。
List(const List& orig) : used(orig.used), capacity(orig.capacity), v((T*) new char[sizeof(T) * capacity]) {
        // now copy only the used ones
        memcpy(v, orig.v, sizeof(T)*capacity);
    }
List(const List& orig) : used(orig.used), capacity(orig.capacity), v((T*) new char[sizeof(T) * capacity]) {
        // now copy only the used ones
        memcpy_s(v, capacity, orig.v, sizeof(T)*capacity);
    }