我正在学习c ++并发现了一个我不明白的问题。我有这个简单的代码:
#include <iostream>
#include <vector>
class Person
{
string * name;
public:
Person(const string & n) : name {new string {n}} {}
~Person() {delete name;}
string getName() const {return *name;}
};
int main()
{
vector<Person> people;
people.push_back(Person("Tom"));
cout << "Name is: " << people.back().getName() << endl;
return 0;
}
当我运行它时,我没有输出。不知道为什么?但是,当我做simillar时,但没有矢量,一切都还可以:
int main()
{
Person tom {"Tom"};
cout << "Name is: " << tom.getName() << endl;
return 0;
}
答案 0 :(得分:9)
正如其他人所说,没有指针就更好了。但是,如果你想知道发生了什么,你得到的原因就是在这一行中people.push_back(Person("Tom"));
创建了Person对象,并将其副本传递给vector。但是,一旦复制了对象,就会执行析构函数删除字符串。
使用指针时,原始Person对象及其副本都指向内存中的相同字符串。析构函数删除字符串,副本中的name
指针不指向任何内容。因此,您会得到未定义的行为。
要解决此问题,要么不使用指针,要么需要定义自己的复制构造函数。例如:
class Person
{
string * name;
public:
Person(const string & n) : name {new string {n}} {}
// copy constructor which makes new string in memory
//based on the original string.
Person(const Person & other) {
name = new string(other.getName());
}
~Person() { delete name; }
string getName() const {return *name;}
};
答案 1 :(得分:3)
您使用的是错误的类型。您的string
已经是字符串类型。写这样的代码。
class Person
{
public:
Person (const string& n) : name(n) { }
~Person() {}
string getName() const { return name; }
private:
string name;
};
如果你坚持在你的成员变量中使用指针,你应该覆盖复制构造函数和重载赋值运算符。
举个例子:
class Person
{
public:
Person (const char* n) : name(new char[strlen(n)+1]) { strcpy(name, n); }
Person (const Person& p) : name(new char[strlen(p.name)+1]) { strcpy(name, p.name); }
~Person() { delete [] name; }
Person& operator=(const Person& p)
{
if ( &p == this ) return *this;
delete [] name;
name = new char[strlen(p.name)+1];
strcpy(name, p.name);
return *this;
}
string getName() const { return name; }
private:
char* name;
};
答案 2 :(得分:1)
您的代码出错的原因已经解释过了,但如果您使用的是C ++ 11,则可以使用emplace_back
:
people.emplace_back("Tom");
尽管如此,使用指针代替普通成员变量只会使程序变得不必要地复杂化。你必须做的内存管理越少越好。阅读Rule of Zero。更好的是,如果您的getName()
函数没有做任何特殊操作,请将其删除,然后公开name
。