因此,我尝试创建一个自定义字符串&向量类(来自名为Cherno的youtube频道)。但是,当我试图用自定义string类在向量类上创建一个复制构造函数时,我得到了这个异常: str是nullptr (发生在字符串复制构造函数中),当我尝试使用基本数据类型(int)时,我也得到了这个异常: std::move(.)返回的nullptr (发生在re_allocate函数上)。
main.cpp:
int main() {
utils::list<int> list;
list.place(5);
utils::list<int> other = list; // Works fine if I remove this line
}字符串复制构造函数:
utils::string::string(const string& other)
: pr_Length(other.pr_Length)
{
// If the other string was not initialized then return
if (!other.pr_Init) {
pr_Init = false;
return;
}
// Allocates a new char*
pr_Data = new char[pr_Length + 1];
// Copy all the char* on other string and copy it here
std::memcpy(pr_Data, other.pr_Data, pr_Length + 1);
// This string is initialized
pr_Init = true;
}向量类:
template<typename T>
class list {
private:
T* pr_Array;
size_t pr_Size;
size_t pr_Cap;
public:
using ValType = T;
using Iterator = list_iterator<list<T>>;
list() {
re_allocate(2);
}
~list() {
destroy_all();
::operator delete(pr_Array, pr_Cap * sizeof(T));
}
list(const list& other)
: pr_Size(other.pr_Size), pr_Cap(other.pr_Cap)
{
re_allocate(pr_Cap);
}
void add(const T& elem) {
if (pr_Size >= pr_Cap) {
re_allocate(pr_Cap + 2);
}
new(&pr_Array[pr_Size]) T(std::move(elem));
pr_Size++;
}
void add(T&& elem) {
if (pr_Size >= pr_Cap) {
re_allocate(pr_Cap + 2);
}
new(&pr_Array[pr_Size]) T(std::move(elem));
pr_Size++;
}
template<typename...Args>
T& place(Args&&... args) {
if (pr_Size >= pr_Cap) {
re_allocate(pr_Cap + 2);
}
new(&pr_Array[pr_Size]) T(std::forward<Args>(args)...);
return pr_Array[pr_Size++];
}
void destroy_back() {
if (pr_Size == 0) {
return;
}
pr_Array[pr_Size].~T();
pr_Size--;
}
void destroy_all() {
for (size_t i = 0; i < pr_Size; i++) {
pr_Array[i].~T();
}
pr_Size = 0;
}
const T& operator[](size_t i) const {
return pr_Array[i];
}
T& operator[](size_t i) {
return pr_Array[i];
}
const size_t size() const {
return pr_Size;
}
size_t size() {
return pr_Size;
}
Iterator begin() {
return Iterator(pr_Array);
}
Iterator end() {
return Iterator(pr_Array + pr_Size);
}
private:
void re_allocate(size_t cap) {
T* newBlock = (T*)::operator new(cap * sizeof(T));
if (cap < pr_Size) {
pr_Size = cap;
}
for (size_t i = 0; i < pr_Size; i++) {
new(newBlock + i) T(std::move(pr_Array[i]));
}
for (size_t i = 0; i < pr_Size; i++) {
pr_Array[i].~T();
}
::operator delete(pr_Array, pr_Cap * sizeof(T));
pr_Array = newBlock;
pr_Cap = cap;
}
};发布于 2022-04-17 02:50:32
utils::list<int> list;main()默认-构造此模板的一个实例。那么,让我们检查一下模板及其默认构造函数。
T* pr_Array;
size_t pr_Size;
size_t pr_Cap; 这个模板类声明这些成员。
list() {构造函数没有成员初始化部分,这三个成员没有默认值,因此这三个类成员都没有初始化为任何内容。它们的初始值是随机垃圾。
re_allocate(2);构造函数然后调用re_allocate(2)。
if (cap < pr_Size) {此时,re_allocate将其参数cap与pr_Size进行比较。但是,如果您一直保持谨慎的注释,那么您将注意到pr_Size并没有初始化到任何东西。从现在起,一切都是未定义的行为。
在这个tempalte类中可能有或不存在其他未定义行为的实例,但是由于这种未定义的行为总是发生在构造函数中,因此无法进一步分析来确定这一点。
例如,pr_reallocate也指pr_Array。当前的情况是,pr_Array也未初始化并包含随机垃圾,因此也存在这种情况。这是否仍然是未定义的行为取决于未定义行为的初始发生是如何固定的。
在复制构造函数中可能有未定义的行为.但是,一步一步.
https://stackoverflow.com/questions/71898867
复制相似问题