在 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);
}
在此代码中,方法名称为 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);
}