为什么不能使用速记将标量值分配给类,而是先声明它,然后设置其值? [英] Why can't I assign a scalar value to a class using shorthand, but instead declare it first, then set its value?

查看:115
本文介绍了为什么不能使用速记将标量值分配给类,而是先声明它,然后设置其值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  ustring a; 
a =test;

,并且重载的=运算符将字符串解析为类作为动态分配的int指针)。但是,以下操作无效:

  ustring a =test 

,因为我收到以下错误:

  test.cpp:4:错误:从'const char [5]'转换为非标量类型'ustring'请求

有办法解决这个错误吗?这可能是一个问题,我的代码,虽然。以下是我到目前为图书馆写的:

  #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 values [i] = input.values [i];
return this;
}
ustring * operator =(char input []){
len = sizeof(input);
values =(int *)malloc(0);
long s = 0; // s =被解析的字符数
int a,b,c,d,contNeed = 0,cont = 0;
for(long i = 0; 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){//这是一个延续(80-bf)
if(cont == contNeed){//不需要继续, 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){//无效字节,使用U + fffd(c0-c1)
values =(int *)realloc ++ s);
values [s-1] = 0xfffd;
} else if(input [i] <0xe0){// 2字节序列的开始(c2-df)
contNeed = 1;
values =(int *)realloc(values,sizeof(int)* ++ s);
values [s-1] =(input [i]& 0x1f)< 6;
} else if(input [i] <0xf0){// 3字节序列开始(e0-ef)
contNeed = 2;
values =(int *)realloc(values,sizeof(int)* ++ s);
values [s-1] =(input [i]& 0x0f)< 12;
} else if(input [i] <0xf5){// 4字节序列开始(f0-f4)
contNeed = 3;
values =(int *)realloc(values,sizeof(int)* ++ s);
values [s-1] =(input [i]& 0x07)< 18;
} else {//限制或无效(f5-ff)
values =(int *)realloc(values,sizeof(int)* ++ s);
values [s-1] = 0xfffd;
}
return this;
}
ustring运算符+(ustring输入){
ustring结果;
result.len = len + input.len;
result.values =(int *)malloc(sizeof(int)* result.len);
for(long i = 0; i result.values [i] = values [i];
for(long i = 0; 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
long s = 0;
for(long i = 0; 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] ;值
r [s + 2] = char(值[1]>> 12 | 0xe0),
r [s + 1] 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]>& 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实际调用构造函数,而不是赋值运算符。 yay,欢迎来到c ++:)



你需要定义一个默认的构造函数和一个 const char * ,因为一旦您定义 构造函数,您需要定义所有构造函数。



很少有其他的事情:




  • 通过引用传递输入ustring

  • pass const char * 而不是 char [] (你不修改输入,char *更常见)

  • sizeof 不是在做您认为的工作,无法正常运行数组参数。它返回 sizeof(char *),而不是 sizeof(array)

  • 返回 的引用

  • 您可以使用 vector< int& 可能会返回一个<$ / code>,以管理您的所有记忆。

  • c $ c> string 。使用 string

    • 它管理自己的内存,因此调用者不需要 $ 删除

    • ); c> printf($); c> ,但在c ++中,通常使用 cout<



    • ul>

      像这样:

        class ustring {
      public:
      //默认构造函数,允许你创建没有参数的类。
      ustring(){...; }
      //允许您从字符串文字创建类。
      ustring(const char * input){...; }
      //复制构造函数,允许从其他实例创建类。
      ustring(const ustring& input){...; }

      //赋值运算符。
      ustring& operator =(const ustring& input){...; return * this; }
      ustring& operator =(const char * input){...; return * this; }
      };

      int main(){
      ustring s,t; //调用默认构造函数。
      s = t; // invokes ustring assignment op。
      s =test; // invokes const char * assignment op。
      ustring u =test; //调用const char *构造函数。
      ustring v(test); //调用const char *构造函数。
      ustring x(u); //调用复制构造函数。
      }

      如果这是c ++,为什么要做所有这些malloc /我没有完全解析的代码,但我想象有一个更简单的方法...看到关于使用矢量的注释。



      正如@迈克尔Aaron Safyan提到注释,如果你为 ustring 类做任何内存分配,你将需要在析构函数中释放它。然而,我想通过切换到内存管理容器 - 矢量& string - 你将避免任何你自己的内存管理,并可以避免写一个析构函数。


      I am writing a UTF-8 library for C++ as an exercise as this is my first real-world C++ code. So far, I've implemented concatenation, character indexing, parsing and encoding UTF-8 in a class called "ustring". It looks like it's working, but two seemingly equivalent ways of declaring a new ustring behave differently. The first way:

      ustring a;
      a = "test";
      

      works, and the overloaded "=" operator parses the string into the class (which stores the Unicode strings as an dynamically allocated int pointer). However, the following does not work:

      ustring a = "test";
      

      because I get the following error:

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

      Is there a way to workaround this error? It probably is a problem with my code, though. The following is what I've written so far for the library:

      #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;
        }
      };
      

      解决方案

      Your problem is that ustring a = "test" actually invokes the constructor, not the assignment operator. yay, welcome to c++ :)

      You'll need to define yourself both a default constructor and one that takes a const char*, because once you define a constructor, you need to define all your constructors.

      A few other things:

      • pass your input ustring by reference
      • pass const char * instead of char[] (you don't modify the input and char* is more common)
      • sizeof isn't doing what you think it's doing, it doesn't work properly for array parameters. It is returning you sizeof(char*), not sizeof(array).
      • return reference to this from your operators.
      • you can use vector<int> values; to manage all your memory for you.
      • encode() should probably return a string. With string:
        • it manages its own memory, so the caller doesn't need to free or delete it.
        • you can use s.append(c); instead of using realloc.
        • you can use printf("%s", s.c_str());, but in c++ you usually use cout << s;
      • consider defining a copy constructor as well.

      Like this:

      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.
      }
      

      If this is c++, why are you doing all this malloc/realloc stuff? I haven't fully parsed that code, but I'd imagine there's a simpler way... see the comment about using vector.

      As @Michael Aaron Safyan mentioned in the comments, if you do any memory allocation for the ustring class, you will want to deallocate it in the destructor. However, I think by switching to memory managed containers - vector & string - you'll avoid any of your own memory management and can avoid writing a destructor.

      这篇关于为什么不能使用速记将标量值分配给类,而是先声明它,然后设置其值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆