当我们可以使用=运算符为字符串赋值时,为什么要在赋值之前使用new运算符为字符串动态分配内存



我不熟悉C++和字符串的概念,为什么我必须使用新运算符来动态分配资源,而我只需要使用=运算符来分配字符串?(这是我的第一个问题,很抱歉造成混乱)

student(const char* n){
    len=strlen(n);
    name=new[len+1];
    strcpy(name,n);
}

学生是班级学生的动态建构者。

class student {
    int len; 
    char *name; 
public: 
    student(const char *);
}

如果我按照下面给出的方式编写我的动态构造函数,它会不会有相同的结果?

student(const char* n){
    len=strlen(n); 
    name=n;
}

char * s;不是字符串。它是一个指向内存块的指针——句柄,其中该块的每个元素都是char的大小。

您必须使用new来分配一个箱子。

然后你把你的把手"系"在那个盒子上。

然后你用数据填充这个框——这就是字符串。

// we have a handle which will fit a box that contains a bunch of "char"
char * s;
// now let's get a box that's big enough to hold the data
// and attach it to the handle
s = new char [len];
// now let's fill up the box with the data from source_str
strcpy (source_str, s);
// also, don't forget that you MUST delete anything that you allocate
delete [] s;

这在编程中是一个极其重要的概念,尤其是对于像C++这样的系统语言。

C++和其他支持类和对象的语言使用构造函数和析构函数来帮助控制对象使用的任何内存,方法是遵循以下循环:

  • 构造对象
  • 用物体做某事
  • 破坏对象

请注意,这与内存管理的周期完全相同。

你现在练习弦乐的原因是为了让你习惯的技术

  • 分配内存块
  • 用它做点什么
  • 然后稍后释放该内存块

这里有一个直接的例子:

#include <iostream>
using namespace std;
char * get_a_string () {
    // notice that s is allocated "on the stack"
    // which means that it goes out of scope and is
    // not available outside of this function
    auto s = "Adam Smith";
    //char * name = s;  // this WILL NOT WORK because the memory that
                        // that s points to will go out of scope
                        // and then name will point to invalid memory
    // we need to make s available to other parts of the
    // program so we allocate some memory "on the heap"
    // because the heap doesn't go out of scope
    char * name = new char [strlen (s)];
    // now since the contents of s have been copied into the heap
    // they'll still be available outside of this function
    strcpy (s, name);
    return name;
}
void do_something (char * c) {
    cout << c << endl;
}
int main () {    
    char * name = get_a_string ();
    do_something (name);
    // rule of thumb:
    //     anything you allocate with "[]" you must also delete with "[]"...
    delete [] name;
}

注意上面程序中的内存循环。请注意,当它是"newed up"one_answers"delete"时。跟踪哪些函数分配了内存,哪些函数删除了内存,这样你就可以在适当的时间新建和删除,这不是很棘手吗?

这里有一个学生班的例子,和你想要的类似。注意内存是如何分配在一个位置并且易于跟踪的:

#include <iostream>
using namespace std;
class Student {
    public:
        // This is NOT a string.
        // It does not contain any data.
        // It only points to a block/box of data that is
        // split into chunks the size of a char
        char * my_name;
        Student (const char * new_name) {
            // we have to find out how long new_name is
            auto name_len = strlen (new_name);
            // now we need to make a box big enough to hold it
            // this is called allocation
            my_name = new char [name_len];
            // now we must copy the contents from the box that
            // new_name points to into the box that my_name points to
            strcpy (new_name, my_name);
        }
        ~Student () {
            // it's very important to free up the memory we allocated
            // in the constructor
            delete [] my_name;
        }
};
int main () {
    // so here the name is allocated and initialized so that we can use some_student elsewhere in our program
    Student some_student ("Adam Smith");
    // making use of the block of memory...
    cout << "student's name is: " << some_student.my_name << endl;
    return 0;
}
// at the end of the scope the destructor for some_student will be called
// which will delete some_student.my_name so that other programs can use
// that memory

这种现代方法使用std::string,但它仍然完全相同。

是的。std::string所做的事情与简单的Student类所做的完全相同。

#include <string>
class Student {
    public:
        std::string name;
        Student (const char * s) {
            // name is a std::string
            // that means that std::string has a constructor
            // and a copy operator which will do exactly what you
            // were doing using new and delete
            // It's just hidden and done for us BUT IT'S STILL BEING DONE.
            name = s;
        }
        ~Student () {
            // ...
        }
        // destructors for all of a class' members will be
        // called at the end of a class' destructor!
        // this means that since "my_name" is a std::string
        // its destructor will delete the memory that std::string
        // allocated in its constructor for me and I don't have to
        // do anything!
};
int main () {
    // so here the name is allocated and initialized
    // so that we can use some_student elsewhere in our program
    auto some_student = Student { "Adam Smith" };
    // making use of the block of memory...
    cout << "student's name is: " << some_student.my_name << endl;
    return 0;
}
// at the end of the scope the destructor for some_student will be called
// which will delete some_student.my_name so that other programs can use
// that memory

以下是Bjarne Stroustrup对学习使用C++编程的看法。

当您分配您拥有的缓冲区时,您可以修改它,但也必须删除它。

我认为不应该汇编上述案例。您正在将const char *分配给char *,这是编译器不应该允许的。如果您将成员更改为const char*,您仍然可以将一个字符串移交给构造函数,该字符串后来不再存在,然后您得到了一个错误的指针。

唯一不重要的是,如果您知道您正在分配常量字符串,例如`constchar*var="myliteralstring"。

最新更新