首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >字符串是nullptr &std::re_allocate函数上返回的nullptr

字符串是nullptr &std::re_allocate函数上返回的nullptr
EN

Stack Overflow用户
提问于 2022-04-17 02:33:43
回答 1查看 50关注 0票数 1

因此,我尝试创建一个自定义字符串&向量类(来自名为Cherno的youtube频道)。但是,当我试图用自定义string类在向量类上创建一个复制构造函数时,我得到了这个异常: str是nullptr (发生在字符串复制构造函数中),当我尝试使用基本数据类型(int)时,我也得到了这个异常: std::move(.)返回的nullptr (发生在re_allocate函数上)。

main.cpp:

代码语言:javascript
复制
int main() {
    utils::list<int> list;
    list.place(5);
    utils::list<int> other = list; // Works fine if I remove this line
}

字符串复制构造函数:

代码语言:javascript
复制
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;
}

向量类:

代码语言:javascript
复制
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;
        }
    };
EN

回答 1

Stack Overflow用户

发布于 2022-04-17 02:50:32

代码语言:javascript
复制
    utils::list<int> list;

main()默认-构造此模板的一个实例。那么,让我们检查一下模板及其默认构造函数。

代码语言:javascript
复制
        T* pr_Array;
        size_t pr_Size;
        size_t pr_Cap;  

这个模板类声明这些成员。

代码语言:javascript
复制
        list() {

构造函数没有成员初始化部分,这三个成员没有默认值,因此这三个类成员都没有初始化为任何内容。它们的初始值是随机垃圾。

代码语言:javascript
复制
            re_allocate(2);

构造函数然后调用re_allocate(2)

代码语言:javascript
复制
            if (cap < pr_Size) {

此时,re_allocate将其参数cappr_Size进行比较。但是,如果您一直保持谨慎的注释,那么您将注意到pr_Size并没有初始化到任何东西。从现在起,一切都是未定义的行为。

在这个tempalte类中可能有或不存在其他未定义行为的实例,但是由于这种未定义的行为总是发生在构造函数中,因此无法进一步分析来确定这一点。

例如,pr_reallocate也指pr_Array。当前的情况是,pr_Array也未初始化并包含随机垃圾,因此也存在这种情况。这是否仍然是未定义的行为取决于未定义行为的初始发生是如何固定的。

在复制构造函数中可能有未定义的行为.但是,一步一步.

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71898867

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档