c++ - 为什么我不能使用速记将标量值分配给类,而是先声明它,然后设置它的值?

标签 c++ class utf-8 overloading

我正在为 C++ 编写一个 UTF-8 库作为练习,因为这是我的第一个真实世界的 C++ 代码。到目前为止,我已经在名为“ustring”的类中实现了连接、字符索引、解析和编码 UTF-8。看起来它在工作,但是两种看似相同的声明新 ustring 的方式表现不同。第一种方式:

ustring a;
a = "test";

有效,重载的“=”运算符将字符串解析到类中(它将 Unicode 字符串存储为动态分配的 int 指针)。但是,以下内容不起作用:

ustring a = "test";

因为我收到以下错误:

test.cpp:4: error: conversion from ‘const char [5]’ to non-scalar type ‘ustring’ requested

有没有办法解决这个错误?不过,这可能是我的代码有问题。以下是我迄今为止为图书馆编写的内容:

#include <cstdlib>
#include <cstring>
class ustring {
  int * values;
  long len;
  public:
  long length() {
    return len;
  }
  ustring * operator=(ustring input) {
    len = input.len;
    values = (int *) malloc(sizeof(int) * len);
    for (long i = 0; i < len; i++)
      values[i] = input.values[i];
    return this;
  }
  ustring * operator=(char input[]) {
    len = sizeof(input);
    values = (int *) malloc(0);
    long s = 0;                                                                 // s = number of parsed chars
    int a, b, c, d, contNeed = 0, cont = 0;
    for (long i = 0; i < sizeof(input); i++)
      if (input[i] < 0x80) {                                                    // ASCII, direct copy (00-7f)
        values = (int *) realloc(values, sizeof(int) * ++s);
        values[s - 1] = input[i];
      } else if (input[i] < 0xc0) {                                             // this is a continuation (80-bf)
        if (cont == contNeed) {                                                 // no need for continuation, use U+fffd
          values = (int *) realloc(values, sizeof(int) * ++s);
          values[s - 1] = 0xfffd;
        }
        cont = cont + 1;
        values[s - 1] = values[s - 1] | ((input[i] & 0x3f) << ((contNeed - cont) * 6));
        if (cont == contNeed) cont = contNeed = 0;
      } else if (input[i] < 0xc2) {                                             // invalid byte, use U+fffd (c0-c1)
        values = (int *) realloc(values, sizeof(int) * ++s);
        values[s - 1] = 0xfffd;
      } else if (input[i] < 0xe0) {                                             // start of 2-byte sequence (c2-df)
        contNeed = 1;
        values = (int *) realloc(values, sizeof(int) * ++s);
        values[s - 1] = (input[i] & 0x1f) << 6;
      } else if (input[i] < 0xf0) {                                             // start of 3-byte sequence (e0-ef)
        contNeed = 2;
        values = (int *) realloc(values, sizeof(int) * ++s);
        values[s - 1] = (input[i] & 0x0f) << 12;
      } else if (input[i] < 0xf5) {                                             // start of 4-byte sequence (f0-f4)
        contNeed = 3;
        values = (int *) realloc(values, sizeof(int) * ++s);
        values[s - 1] = (input[i] & 0x07) << 18;
      } else {                                                                  // restricted or invalid (f5-ff)
        values = (int *) realloc(values, sizeof(int) * ++s);
        values[s - 1] = 0xfffd;
      }
    return this;
  }
  ustring operator+(ustring input) {
    ustring result;
    result.len = len + input.len;
    result.values = (int *) malloc(sizeof(int) * result.len);
    for (long i = 0; i < len; i++)
      result.values[i] = values[i];
    for (long i = 0; i < input.len; i++)
      result.values[i + len] = input.values[i];
    return result;
  }
  ustring operator[](long index) {
    ustring result;
    result.len = 1;
    result.values = (int *) malloc(sizeof(int));
    result.values[0] = values[index];
    return result;
  }
  char * encode() {
    char * r = (char *) malloc(0);
    long s = 0;
    for (long i = 0; i < len; i++) {
      if (values[i] < 0x80)
        r = (char *) realloc(r, s + 1),
        r[s + 0] = char(values[i]),
        s += 1;
      else if (values[i] < 0x800)
        r = (char *) realloc(r, s + 2),
        r[s + 0] = char(values[i] >> 6 | 0x60),
        r[s + 1] = char(values[i] & 0x3f | 0x80),
        s += 2;
      else if (values[i] < 0x10000)
        r = (char *) realloc(r, s + 3),
        r[s + 0] = char(values[i] >> 12 | 0xe0),
        r[s + 1] = char(values[i] >> 6 & 0x3f | 0x80),
        r[s + 2] = char(values[i] & 0x3f | 0x80),
        s += 3;
      else
        r = (char *) realloc(r, s + 4),
        r[s + 0] = char(values[i] >> 18 | 0xf0),
        r[s + 1] = char(values[i] >> 12 & 0x3f | 0x80),
        r[s + 2] = char(values[i] >> 6 & 0x3f | 0x80),
        r[s + 3] = char(values[i] & 0x3f | 0x80),
        s += 4;
    }
    return r;
  }
};

最佳答案

你的问题是ustring a = "test"实际上调用构造函数,而不是赋值运算符。是的,欢迎使用 C++ :)

您需要自己定义一个默认构造函数和一个接受 const char* 的构造函数,因为一旦您定义了一个构造函数,您就需要定义所有您的构造函数。

其他一些事情:

  • 通过引用传递您的输入 ustring
  • 通过 const char *而不是 char[] (你不修改输入,char*更常见)
  • sizeof没有按照您的想法去做,它 doesn't work properly for array parameters .它正在返回你sizeof(char*) , 不是 sizeof(array) .
  • 返回引用 this来自您的运营商。
  • 你可以使用vector<int> values;为您管理所有内存。
  • encode()可能应该返回 string .与 string :
    • 它管理自己的内存,所以调用者不需要 freedelete
    • 你可以使用s.append(c);而不是使用 realloc .
    • 你可以使用printf("%s", s.c_str()); , 但在 C++ 中你通常使用 cout << s;
  • 也考虑定义一个复制构造函数。

像这样:

class ustring {
 public:
  // Default constructor, allows you to create your class with no arguments.
  ustring() { ...; }
  // Allows you to create your class from string literals.
  ustring(const char *input) { ...; }
  // Copy constructor, allows you to create your class from other instances.
  ustring(const ustring &input) { ...; }

  // Assignment operators.
  ustring &operator=(const ustring &input) { ...; return *this; }
  ustring &operator=(const char *input) { ...; return *this; }
};

int main() {
  ustring s, t;  // invokes default constructor.
  s = t;         // invokes ustring assignment op.
  s = "test";    // invokes const char* assignment op.
  ustring u = "test";  // invokes const char* constructor.
  ustring v("test");   // invokes const char* constructor.
  ustring x(u);  // invokes copy constructor.
}

如果这是 C++,你为什么要做所有这些 malloc/realloc 的东西?我还没有完全解析该代码,但我想有一种更简单的方法......请参阅有关使用 vector 的评论。

正如@Michael Aaron Safyan 在评论中提到的,如果您为 ustring 分配任何内存类,你会想在析构函数中释放它。但是,我认为通过切换到内存管理容器( vector 和字符串),您将避免任何自己的内存管理,并且可以避免编写析构函数。

关于c++ - 为什么我不能使用速记将标量值分配给类,而是先声明它,然后设置它的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2752240/

相关文章:

java - Java UTF-8 字符集异常可能吗?

java - NoClassDefFoundError 在 Linux 上运行 .jar

c++ - Bison 可以解析 UTF-8 字符吗?

.net - 将非托管 C++ 与 F# 混合用于物理 : worth it?

c++ - 调试时从文件中读入

c++ - 使用命名空间与使用类

C++ 多线程类方法

java - 如何将某些语言单词的十六进制值恢复为 UTF-8

c# - 如何将 C++ 结构转换为 C# 等效结构?

c++ - 将对象添加到 vector