在 C++ 中使用字符串作为参数和参数或 return 类型的正确方法是什么

What is correct way to use string as an argument and parameter or return type in C++

在此代码中,方法名称为 setname()。 在此方法中,我使用参数 (Char *aname),参数 "Name_Student"(调用时)。

但出现错误:"deprecated conversion from string constant to 'char*' [-Wwrite-strings]"

#include <iostream>
#include <string>

using namespace std;

class student
{
    int rollno;
    char *name;
    public:
        void setname( char *aname);
        void setrollno(int arollno);
        char getname() {return *name;}
        int getrollno() {return rollno;}
};

void student::setname(char *aname)
{
 name = aname;
}

void student::setrollno(int arollno)
{
 rollno = arollno;
}


int main()
{
student astudent;
astudent.setname("Name_Student"); //Getting Error Here
astudent.setrollno(10);
astudent.getname();
astudent.getrollno();
return (0);
}

我想知道为什么会出现此错误。任何人都可以解释不同的场景来理解这一点。

当我在调用时在参数中使用转换

.setname((char*)"Name_Student"); //Working Fine

当我将这个字符串存储在一个数组中并像这样传递该数组时

char name_s[] = "Name_Student";
.setname(name_s); // working fine

您应该在 'char*' 之前插入 'const',但是这里已经回答了这个问题:How to get rid of `deprecated conversion from string constant to ‘char*’` warnings in GCC?

可能您要找的内容已得到解答here

这里还有对我在问题下方发布的关于字符串的评论的回复:

在这两个 C/C++ 中,您都可以选择是按引用还是按值传递。有两种方法可以做到这一点——*(指针)运算符和 &(地址)运算符。但是,在您的情况下,使用按值传递(而不是按引用传递)是完全可以的:

#include <iostream>
#include <string>

using namespace std;

class student
{
    int rollno;
    string name;
    public:
        void setname(string name) { this->name = name; }
        void setrollno(int rollno) { this->rollno = rollno; }
        string getname() { return name; }
        int getrollno() { return rollno; }
};

int main()
{
  student astudent;
  astudent.setname("Name_Student"); // here you pass by value
  astudent.setrollno(10);
  astudent.getname();               // name is set, so everything is okay :)
  astudent.getrollno();
  return (0);
}

如果你真的想进入整个引用传递的过程,你可以像这样轻松地修改 setname() 函数(你还必须用 string* name 和 getname() with return *name):

void setname(string& name) { this->name = name; }

在这种情况下,调用

astudent.setname("Name_Student");

不可能,您必须先创建对象,然后将其传递给函数:

string newName = "Name_Student";
astudent.setname(newName);

如果您想更改 class 之外的名称,这很有用,但它可能被视为违反 OOP 原则的东西,因为更改对象的内容只能通过严格定义的某些内容来完成class代表的是套路,而不只是套路

这是你的代码的重做,用一个小例子来说明我的意思:

#include <iostream>
#include <string>

using namespace std;

class student
{
    int rollno;
    string* name;  // very important! otherwise you will just store a COPY of the new name instead of a reference to the object that was passed to setname()
    public:
        // here we pass by reference a string object!
        void setname(string& name) { this->name = &name; }
        void setrollno(int rollno) { this->rollno = rollno; }
        string getname() { return *name; }
        int getrollno() { return rollno; }
};

int main()
{
  student astudent;
  string str = "Name_Student";

  astudent.setname(str);        // we pass by reference here!
  cout << astudent.getname() << endl;
  str += "LALALA";              // because we have passed the string object by reference to the astudent object we can change its contents outside the class without using the setter provided by the class
  cout << astudent.getname() << endl;

  return (0);
}

以上代码的输出将是:

Name_Student
Name_StudentLALALA

那么在你的情况下,我认为你不需要任何引用传递。还有一点建议——在用 C++ 编程时尽量使用 C++ 提供的特性。尽管在某些情况下您可能想坚持使用旧的 char* 处理方式,但它只是糟糕的编码风格。 std::string 还提供了 c_str() 函数,return 是一个 C 字符串(参见 here了解更多信息)。

除非您有特定理由使用 char*,否则您应该使用 std::string。我认为使用 std::string* 的想法很糟糕,因为学生姓名的生命周期与学生对象是分开的。考虑以下代码:

student get_student()
{
    // get the student from the database
    string name = "some name";
    int rollno = 1;
    student s;
    s.setname(name);
    s.setrollno(rollno);
    return s;
}

如果您随后尝试使用学生的姓名,您将引用一个不再存在的对象。你可以试试:

student s = get_student();
cout << s.getname() << endl;

我认为最好的选择是使用 string 作为名称。这样您就不必担心内存分配和生命周期管理。您还应该有一个构造函数,而不仅仅是设置器(除非您要使用 POD)。

class student {
    int rollno;
    string name;
    public:
        student(const string& name, int rollno): name(name), rollno(rollno) {}
        void setname(const string& name) { this->name = name; }
        void setrollno(int rollno) { this->rollno = rollno; }
        const string& getname() { return name; }
        int getrollno() { return rollno; }
};

如果您的 setname 将参数作为 const string& 那么您仍然可以使用 setname("Name") 因为这将创建一个右值,它可以绑定到 const 引用。

int main(int argc, char *argv[]) {
    student astudent("Student's Name", 10);
    cout << "Roll #: " << astudent.getrollno() << '\n';
    cout << "Name: " << astudent.getname() << '\n';
    astudent.setname("New name");
    cout << "Name: " << astudent.getname() << '\n';
    string n{"Yet Another Name"};
    astudent.setname(n);
    cout << "Name: " << astudent.getname() << '\n';

    return (0);
}