c++ - 为数据缺少默认构造函数的链表创建节点

标签 c++ linked-list initialization c++14 default-constructor

我正在尝试实现一个表示双向链表的类,并且我有一个函数 createNode() 返回一个新的 Node (一个模板类)其所有成员都已初始化。此函数将用于创建已知大小但未向其传递数据的链表。对于大多数数据类型,这都有效。但是,这对没有默认构造函数的类起作用,因为它们不能在没有参数的情况下进行初始化。这是展示这一点的最小代码:

class Test // A class without a default constructor
{
public:
    Test(int value) : value_{ value } { };
private:
    int value_;
};

template<typename T>
struct Node
{
    Node* prev;
    Node* next;
    T value;
};

template<typename T>
Node<T>* createNode()
{
    return new Node<T>{ nullptr, nullptr, T() }; // How do I change T() so
                                                 // that I can use classes
                                                 // without default constructors?
}

int main()
{
    Node<Test>* testNode = createNode<Test>();
    delete testNode;
}

基本上,我的最终目标是能够创建一个链表,它可以保存未初始化的节点,同时跟踪哪些节点已初始化或未初始化。我记得在我的一本旧教科书中读过有关解决此问题的方法,该方法涉及使用分配器(用于处理对象的构造/破坏),但我完全不记得确切的技术。那么我应该怎么做呢?

最佳答案

使用 std::optional<T>如果你可以访问 C++17,或者 boost::optional<T>如果你不这样做。

template<typename T>
struct Node
{
    Node* prev;
    Node* next;
    std::optional<T> value;  // or boost::optional<T> value;
};

template<typename T>
Node<T>* createNode()
{
    return new Node<T>{ nullptr, nullptr, std::nullopt /* or boost::none */ };
}

如果您无法访问 C++17 并且不想包含 boost,您可以自己推出 optional类似这样的模板:

struct nullopt_t {};
nullopt_t nullopt;

template <typename T>
class optional
{
public:
    template <typename... Args>
    optional(Args&&... args)
        : ptr{new ((void*)&storage) T(std::forward<Args>(args)...)}
    {}

    optional(nullopt_t)
        : ptr{nullptr}
    {}

    ~optional()
    {
        if (ptr) {
            ptr->~T();
        }
    }

    optional& operator=(T obj)
    {
        if (ptr) {
            *ptr = std::move(obj);
        } else {
            ptr = new ((void*)&storage) T(std::move(obj));
        }
        return *this;
    }

    explicit operator bool()
    {
        return ptr != nullptr;
    }

    T& value()
    {
        if (!ptr) {
            throw std::exception();
        }
        return *ptr;
    }

    // Other const-correct and rvalue-correct accessors left
    // as an exercise to the reader
private:
    std::aligned_storage_t<sizeof(T), alignof(T)> storage;
    T* ptr;
};

Live Demo

关于c++ - 为数据缺少默认构造函数的链表创建节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48591854/

相关文章:

java - 使用通用链表但在弹出时强制使用(cast)

java - 为什么我的算法不检查链表的最后一个元素?

performance - Big O 无缓冲区链表去重速度

c++ - 为什么单独初始化一个新变量是有效的?

C# 构造函数重载 : new object. FromOtherObject()?

c++ - 未定义行为是否依赖于 C++ 中的编译器?

c# - C# 中的 void* 是什么?

c++ - 为什么我的 char[] 存储垃圾?

c++ - 模板成员类的模板别名

java.lang.OutOfMemoryError : PermGen space