【发布时间】:2018-05-25 14:18:36
【问题描述】:
我正在练习在 C++ 中使用模板和类。我的目标是为双端队列编写一个模板类。它将具有“insert_head”、“insert_tail”、“remove_tail”和“remove head”的功能,以及使用“cout”打印的能力。此外,“=”运算符必须能够用于将类的一个实例复制到另一个实例。这是我当前的代码:
#ifndef DEQUE_H
#define DEQUE_H
template <typename T>
class Deque {
public:
Deque(int size = 0, int capacity = 1000) : size_(size), capacity_(capacity)
{}
Deque(Deque & d) : x_(d.x()), size_(d.size()), capacity_(d.capacity()) {}
std::ostream & operator<<(std::ostream & cout) {
cout << '[';
if (size_ > 0) {
for (int i = 0; i < (size_ - 1)* sizeof(T); i += sizeof(T)) {
std::cout << *(x_ + i) << ',';
}
cout << *(x_ + (size_ - 1)* sizeof(T));
}
cout << ']';
return cout;
}
Deque operator=(Deque d) {
Deque dq(d);
return dq;
}
void print_test() {
std::cout << '[';
if (size_ > 0) {
for (int i = 0; i < (size_ - 1)* sizeof(T); i += sizeof(T)) {
std::cout << *(x_ + i) << ',';
}
std::cout << *(x_ + (size_ - 1)* sizeof(T));
}
std::cout << ']';
}
int * x() {
return x_;
}
int size() {
return size_;
}
int capacity() {
return capacity_;
}
bool is_empty() {
return size_ == 0;
}
void insert_tail(T tail) {
if (size_ < capacity_) {
*(x_ + sizeof(T) * size_) = tail;
size_++;
} else {
// throw overflow
}
}
T remove_tail() {
if (size_ > 0) {
T ret = *(x_ + sizeof(T) * (size_ - 1));
std::cout << ret;
size_--;
return ret;
} else {
// throw underflow
}
}
void insert_head(T head) {
if (size_ > 0 && size_ < capacity_) {
for (int i = (size_ - 1) * sizeof(T); i < 0; i -= sizeof(T)) {
*(x_ + i + sizeof(T)) = *(x_ + i);
}
}
if (size_ < capacity_) {
*x_ = head;
size_++;
} else {
// throw overflow
}
}
T remove_head() {
if (size_ > 0) {
T ret = *x_;
for (int i = sizeof(T); i < size_* sizeof(T); i += sizeof(T)) {
*(x_ + i - sizeof(T)) = *(x_ + i);
}
size_--;
return ret;
} else {
// throw underflow
}
}
private:
T * x_;
int size_;
int capacity_;
};
#endif
这是我使用该类的测试代码:
#include <iostream>
#include "Deque.h"
int main(int argc, char const *argv[])
{
Deque< int > dq;
dq.insert_head(1);
// dq.insert_head(2); // adding head when not empty causes bug
dq.insert_tail(3);
dq.insert_tail(4);
dq.insert_tail(5);
dq.print_test(); std::cout << std::endl;
// std::cout << dq; // '<<' not overloaded properly'
std::cout << dq.remove_head() << " head removed\n";
// int x = dq.remove_head(); // seg faults when assigning returned value to a variable
dq.insert_tail(2);
dq.print_test();
std::cout << std::endl;
Deque< int > dq1(dq);
Deque< int > dq2;
// dq2 = dq1; // '=' not overloaded properly
return 0;
}
我的四个问题中的每一个都在我的测试文件中被注释掉的代码行中,这里是进一步的解释:
当调用“dq.insert_head(2)”并且 dq 不为空(大小 > 0)时,我尝试将双端队列中的所有其他元素移到一个位置,以便可以在那里插入新值,有问题,元素没有移过来。
"std::cout
当试图从双端队列中删除头部或尾部时,我试图返回删除的值。在未注释掉的代码行中,返回值按原样打印,但下面的代码行会导致 seg 错误。是因为我试图将模板变量分配给整数变量吗?
我的最后一个问题是 '=' 运算符没有将类的一个实例复制到另一个实例。我的目标是创建该类的一个新实例,然后返回该实例(如您在“Deque operator=(Deque d)”中所见),但这并没有像我希望的那样工作。使用模板类重载“=”函数的最佳方法是什么。
感谢您的帮助,非常感谢您回答这些问题。
【问题讨论】:
-
你在哪里为
x分配内存?删除您的sizeof(T)条款。此外,请考虑在适当的情况下使用 const 引用。 -
1) 您可以通过使用调试器单步执行您的代码来找到 1、3、4 的原因(这就是任何想要回答您的人,很可能无论如何都会这样做)。 2) 关于 (2) - 您当前的重载接受
deque作为第一个参数,ostream作为第二个参数,有效地允许您将 `dq . If you want to output it via the use of cout ostream 作为第一个参数)。 -
为什么要重载
=运算符? -
您的
x方法无条件返回int*,而不是T*。您的operator=没有为实例的任何成员分配东西,它只是创建一个新的Deque并返回它,这是没有意义的。实现复制构造和operator=很难/很烦人;我强烈建议阅读并使用the copy-and-swap idiom 来显着减少重复代码;如果复制构建和销毁工作,operator=很容易。 -
和
*(x+i)语法最终可能会让您感到困惑。我建议使用数组语法x[i]
标签: c++ class templates cout overloading