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

时间:2015-10-28 19:15:23

标签: c++ string dynamic new-operator allocation

我是C ++和字符串概念的新手,为什么我必须使用new运算符来动态分配资源,而我只能使用=运算符分配字符串? (这是我的第一个问题,对于弄乱而感到抱歉)

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

2 个答案:

答案 0 :(得分:1)

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”和“deleted”。跟踪哪些功能分配了内存以及哪些功能已将其删除以便您可以在适当的时间进行新建和删除,这不是很棘手吗?

以下是类似于您的学生类的示例。注意如何在一个地方分配内存并且易于跟踪:

#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 ,但它仍然完全相同

YES。 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对learning to program using C++所说的话。

答案 1 :(得分:0)

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

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

唯一不重要的是,如果你知道你正在分配常量字符串,例如`const char * var =&#34;我的文字字符串&#34;。