是否可以在不使用C ++中的堆的情况下创建String类?

时间:2018-11-21 18:34:41

标签: c++ class memory-management stack static-allocation

我想写自己的String类,其接口类似于std :: string。字符串类不得使用动态内存分配。

我需要一个c-tor:

String(char* ptrToFirstCharInTab, char* ptrToLastElementInTab);

应该有一个包含不同(不知道)元素数量的选项卡,所以我在编译时不知道大小。

在我看来这是不可能的,因为如果在编译之前我们不知道数组的大小,那么我们就不能在没有动态分配的情况下创建它-当然,要为500个char创建缓冲区,然后String类只能是500个,这不是我的期望。

你有什么主意吗?也许有什么办法可以使我缩小以适应buffor?感谢您的帮助!

3 个答案:

答案 0 :(得分:4)

您问:

  

你有什么主意吗?也许有什么办法可以使我缩到合适的程度呢?

理论上,可以。您可以使用预分配的缓冲区作为堆内存。但是,您必须编写自己的代码来管理该缓冲区。可行,但我不建议这样做。

答案 1 :(得分:1)

您问:

  

是否可以在不使用C ++中的堆的情况下创建String类?

实际上,是的,可以通过使用from PyQt5 import QtCore, QtGui, QtWidgets class Foo(QtWidgets.QWidget): def __init__(self, parent=None): super(Foo, self).__init__(parent) self.setGeometry(QtCore.QRect(200, 100, 800, 800)) self.button = Button() self.paint = Createpaintwidget() self.button.valuesChanged.connect(self.paint.set_size_squares) self.button.valueChanged.connect(self.paint.set_size_round) self.lay = QtWidgets.QVBoxLayout(self) self.lay.addWidget(self.paint) self.lay.addWidget(self.button) class Createpaintwidget(QtWidgets.QWidget): def __init__(self): super().__init__() self.sizeHint() self.setBackgroundRole(QtGui.QPalette.Base) self.setAutoFillBackground(True) self._size = QtCore.QSizeF() self._path = QtGui.QPainterPath() self._rect = QtCore.QRectF() self._type = QtGui.QRegion.Rectangle self._factor = 1.0 self._pos = QtCore.QPointF() self._initial_flag = False fnt = self.font() fnt.setPointSize(20) self.setFont(fnt) def showEvent(self, event): if not self._initial_flag: self._pos = self.rect().center() self._initial_flag = True @QtCore.pyqtSlot(int,int) def set_size_squares(self, w, h): self._size = QtCore.QSizeF(w, h) self._type = QtGui.QRegion.Rectangle self.updatePath() @QtCore.pyqtSlot(int) def set_size_round(self, v): self._size = QtCore.QSizeF(v, v) self._type = QtGui.QRegion.Ellipse self.updatePath() def paintEvent(self, event): pen = QtGui.QPen() brush = QtGui.QBrush(QtCore.Qt.black) painter = QtGui.QPainter(self) painter.setRenderHint(QtGui.QPainter.Antialiasing) painter.setPen(pen) painter.setBrush(brush) painter.translate(self.rect().center()) painter.scale(self._factor, self._factor) painter.translate(-self.rect().center()) painter.translate(self._pos) painter.drawPath(self._path) if self._type == QtGui.QRegion.Rectangle: painter.fillRect(self._rect, QtGui.QBrush(QtCore.Qt.gray, QtCore.Qt.Dense7Pattern)) painter.setBrush(QtGui.QBrush(QtCore.Qt.NoBrush)) painter.drawRect(self._rect) elif self._type == QtGui.QRegion.Ellipse: painter.setBrush(QtGui.QBrush(QtCore.Qt.gray, QtCore.Qt.Dense7Pattern)) painter.drawEllipse(self._rect) def mousePressEvent(self, event): QtWidgets.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.OpenHandCursor)) self._initial_pos = event.pos() super().mousePressEvent(event) def mouseMoveEvent(self, event): delta = event.pos() - self._initial_pos self._path.translate(delta) self._rect.translate(delta) self.update() self._initial_pos = event.pos() super().mouseMoveEvent(event) def mouseReleaseEvent(self, event): QtWidgets.QApplication.restoreOverrideCursor() super().mouseReleaseEvent(event) def updatePath(self): fm = QtGui.QFontMetrics(self.font()) r = QtCore.QRectF(QtCore.QPointF(), self._size) r.moveCenter(QtCore.QPointF()) self._rect = QtCore.QRectF(r) self._path.moveTo(QtCore.QPointF()) p = QtCore.QPointF(self._size.width()/2 + 75 ,0) self._path.lineTo(p) self._path.lineTo(p + QtCore.QPoint(-16, -16)) self._path.lineTo(p) self._path.moveTo(p) self._path.lineTo(p + QtCore.QPoint(-16, 16)) self._path.lineTo(p) self._path.addText(p + QtCore.QPoint(16, 0) , self.font(), "x") self._path.moveTo(QtCore.QPointF()) p = QtCore.QPointF(0, -self._size.height()/2 - 75) self._path.lineTo(p) self._path.lineTo(p + QtCore.QPoint(16, 16)) self._path.lineTo(p) self._path.moveTo(p) self._path.lineTo(p + QtCore.QPoint(-16, 16)) self._path.addText(p + QtCore.QPoint(0, -16) , self.font(), "y") if self._type == QtGui.QRegion.Rectangle: pl = r.bottomLeft() + QtCore.QPointF(0, 75) pr = r.bottomRight() + QtCore.QPointF(0, 75) self._path.moveTo(pl) self._path.lineTo(pr) for p in (pl, pr): self._path.moveTo(p+ QtCore.QPoint(0, -40)) self._path.lineTo(p+ QtCore.QPoint(0, 20)) self._path.moveTo(p+ QtCore.QPoint(10, -10)) self._path.lineTo(p+ QtCore.QPoint(-10, 10)) word = "{}".format(self._size.width()) p = QtCore.QPointF(r.center().x() - 0.5*fm.width(word) , r.bottom() + 100) self._path.addText(p , self.font(), word) pt = r.topLeft() + QtCore.QPointF(-75, 0) pb = r.bottomLeft() + QtCore.QPointF(-75, 0) self._path.moveTo(pt) self._path.lineTo(pb) for p in (pt, pb): self._path.moveTo(p+ QtCore.QPoint(40, 0)) self._path.lineTo(p+ QtCore.QPoint(-20, 0)) self._path.moveTo(p+ QtCore.QPoint(10, -10)) self._path.lineTo(p+ QtCore.QPoint(-10, 10)) word = "{}".format(self._size.height()) p = QtCore.QPointF(r.left() -80 - fm.width(word) , r.center().y() + 0.5*fm.height()) self._path.addText(p , self.font(), word) if self._type == QtGui.QRegion.Ellipse: pl = r.bottomLeft() + QtCore.QPointF(0, 75) pr = r.bottomRight() + QtCore.QPointF(0, 75) self._path.moveTo(pl) self._path.lineTo(pr) for p in (pl, pr): self._path.moveTo(p+ QtCore.QPoint(0, -self._size.height()/2 - 20)) self._path.lineTo(p+ QtCore.QPoint(0, 10)) self._path.moveTo(p+ QtCore.QPoint(10, -10)) self._path.lineTo(p+ QtCore.QPoint(-10, 10)) word = "{}".format(self._size.width()) p = QtCore.QPointF(r.center().x() - 0.5*fm.width(word) , r.bottom() + 100) self._path.addText(p , self.font(), word) self.update() def wheelEvent(self, event): self._factor *= 1.01**(event.angleDelta().y()/15.0) self.update() super().wheelEvent(event) class Button(QtWidgets.QWidget): valueChanged = QtCore.pyqtSignal(int) valuesChanged = QtCore.pyqtSignal(int,int) def __init__(self, parent=None): super(Button, self).__init__(parent) roundbutton = QtWidgets.QPushButton('Round') squarebutton = QtWidgets.QPushButton('Square') Alay = QtWidgets.QVBoxLayout(self) Alay.addWidget(roundbutton) Alay.addWidget(squarebutton) self.value = QtWidgets.QLabel() roundbutton.clicked.connect(self.getbuttonfunc) squarebutton.clicked.connect(self.sqaurebuttonfunc) @QtCore.pyqtSlot() def getbuttonfunc(self): number, ok = QtWidgets.QInputDialog.getInt(self, self.tr("Set Number"), self.tr("Input:"), 1, 1) if ok: self.valueChanged.emit(number) @QtCore.pyqtSlot() def sqaurebuttonfunc(self): number, ok = QtWidgets.QInputDialog.getInt(self, self.tr("Set Number"), self.tr("Input:"), 1, 1) if ok: self.valuesChanged.emit(number, number) if __name__ == '__main__': import sys app = QtWidgets.QApplication(sys.argv) w = Foo() w.show() sys.exit(app.exec_()) 或类似的平台相关功能来动态地在堆栈上分配内存。查看此其他答案以获取更多详细信息: C++ How to allocate memory dynamically on stack?

我建议您反对,并绝对确保这是开始之前的最佳选择。

更新: 我使用_alloca创建了一个带有内联构造函数的示例,用于演示:

编译器资源管理器链接: https://godbolt.org/z/M1F5VD

完整代码:

gcc

答案 2 :(得分:1)

我对您的问题有点困惑。您想要std:: string没有堆且没有大小限制。很抱歉为您带来这个:您不可能拥有无限的记忆力。

如果您有一个专用于字符串的内存池,而每个字符串的大小都不固定,则分配器可以这样做。 容器的默认分配器执行的是新的,但是您可以替换它而不必重复字符串的内部。