在没有开销的情况下实现 push_back 的最佳方法是什么
what's the optimum way to implement push_back without overhead
我正在尝试实现一个队列,您可以在其中将要添加到队列中的对象传递给它。
struct Node {
T data;
Node *next, *prev;
};
// Push data to the back of the list.
template <class T> T& CircularQueue<T>::push_back(const T&& new_data)
{
Node* new_node = new Node();
new_node->data = std::move(new_data);
link_node(new_node, m_head);
return new_node->data;
}
我当前方法的问题是开销太大(因为我来自 C,所以这些事情困扰着我)。例如图片我将从 MyClass 添加一个对象:
CircularQueue<MyClass> list;
list.push_back(MyClass(arg1, arg2));
第一个问题是 MyClass 需要有一个不带参数的构造函数才能在 Node* new_node = new Node();
中使用,因为创建 Node 结构将调用其中对象的构造函数,即 MyClass。我试过 std::vector,它不需要这个。
第二个问题是开销太大,list.push_back(MyClass(arg1, arg2));
会在栈中创建一个右值对象然后发送到push_back
,然后在堆中创建一个新对象(没有参数列表)然后使用移动赋值将其所有成员移动到新对象,有没有更快的解决方案?
你可以emplace_back你的节点
template <class T>
class CircularQueue {
template<typename... U>
T &emplace_back(U&&... u)
{
Node *new_node = new Node{{std::forward<U>(u)...}}; // <data is created here
// link_node(new_node, m_head);
return new_node->data;
}
};
void foo() {
CircularQueue<Data> x;
// Do not create a Data, pass the parameters you need to create
x.emplace_back(10, 20);
// If you actually need to, you can of course copy or move an existing Data
Data y(20, 30);
x.emplace_back(y); // copies y
x.emplace_back(std::move(y)); // moves y
}
我正在尝试实现一个队列,您可以在其中将要添加到队列中的对象传递给它。
struct Node {
T data;
Node *next, *prev;
};
// Push data to the back of the list.
template <class T> T& CircularQueue<T>::push_back(const T&& new_data)
{
Node* new_node = new Node();
new_node->data = std::move(new_data);
link_node(new_node, m_head);
return new_node->data;
}
我当前方法的问题是开销太大(因为我来自 C,所以这些事情困扰着我)。例如图片我将从 MyClass 添加一个对象:
CircularQueue<MyClass> list;
list.push_back(MyClass(arg1, arg2));
第一个问题是 MyClass 需要有一个不带参数的构造函数才能在 Node* new_node = new Node();
中使用,因为创建 Node 结构将调用其中对象的构造函数,即 MyClass。我试过 std::vector,它不需要这个。
第二个问题是开销太大,list.push_back(MyClass(arg1, arg2));
会在栈中创建一个右值对象然后发送到push_back
,然后在堆中创建一个新对象(没有参数列表)然后使用移动赋值将其所有成员移动到新对象,有没有更快的解决方案?
你可以emplace_back你的节点
template <class T>
class CircularQueue {
template<typename... U>
T &emplace_back(U&&... u)
{
Node *new_node = new Node{{std::forward<U>(u)...}}; // <data is created here
// link_node(new_node, m_head);
return new_node->data;
}
};
void foo() {
CircularQueue<Data> x;
// Do not create a Data, pass the parameters you need to create
x.emplace_back(10, 20);
// If you actually need to, you can of course copy or move an existing Data
Data y(20, 30);
x.emplace_back(y); // copies y
x.emplace_back(std::move(y)); // moves y
}