如何在实例化时使用用户输入在类构造函数中初始化私有char *
How to initialize a private char * in a Class constructor with user input upon instantiation
下面的程序在构造函数定义中崩溃。显然,我不能使用构造函数将给定的字符串复制到brand变量到私有类变量_brand中。
我哪里错了?这个想法是接受用户输入的品牌名称,并将这个名称的类实例化为_brand。
编辑:请不要建议使用std::string类,因为我在这个问题上坚持使用c-string。这是c++大学中级课程作业中的一小部分。教授想让我们在学习STL字符串课程之前有c字符串的基础知识。指令明确禁止使用std::string。Thx .
#include <iostream>
#include <cstring>
class Cheese {
char * _brand;
public:
Cheese(const char *); // constructor declaration
char * getBrand();
};
Cheese::Cheese(char const * b) { // constructor definition
strcpy(_brand, b); // CRASHES HERE
}
char * Cheese::getBrand() {
return _brand;
}
int main(int argc, const char * argv[]) {
const char * brand = "Cabot";
Cheese * cheddar = new Cheese(brand);
std::cout << cheddar -> getBrand();
return 0;
}
正如其他人指出的那样,_brand
只是一个指针。它不存储字符串,它指向字符串开始的内存地址。你必须预留内存空间。
解决方法很简单:
_brand = new char[strlen(b)+1]; // Reserve memory chunk for your copied string. Add +1 for string terminator ' '
strcpy(_brand, b); // "CRASHES HERE" should be gone now
通过输入new, _brand变量现在指向一个有效的内存块(由你的程序拥有),足够大来存储你复制的字符串。
最后,不要忘记释放 _brand
以避免内存泄漏。
_brand
只是一个指针,当你的类被创建时,它背后没有内存分配。当您尝试对它执行strcpy
时,它可能是NULL
或指向您的程序无法访问的内存,因此它崩溃了。您可以使用strdup
来分配内存,但随后必须使用free
,例如在析构函数中。最好是使用标准的c++ std::string
.
在C和c++中,指针指向内存中的某个位置。访问指针允许您从它指向的位置进行读写操作。在程序中,成员_brand
是一个未初始化的指针,它没有定义它指向的位置。对未初始化的指针进行读写是未定义的行为,这意味着什么都可能发生,也可能什么都不发生。这通常意味着程序会崩溃,但由于行为是未定义的,结果可能会更糟——例如,它可能真的会写入内存中的随机位置。
你需要实际的内存而不仅仅是一个指针。以下是3种合理的方法:
数组#include <iostream>
#include <cstring>
class Cheese {
char _brand[256];
public:
Cheese(const char *); // constructor declaration
char * getBrand();
};
Cheese::Cheese(char const * b) { // constructor definition
strncpy(_brand, b, sizeof(_brand)); // copies up to 255 characters, plus terminating
}
char * Cheese::getBrand() {
return _brand;
}
int main(int argc, const char * argv[]) {
const char * brand = "Cabot";
Cheese * cheddar = new Cheese(brand);
std::cout << cheddar -> getBrand();
delete cheddar;
return 0;
}
指针#include <iostream>
#include <cstring>
class Cheese {
char * _brand;
public:
Cheese(const char *); // constructor declaration
~Cheese(); // destructor declaration
char * getBrand();
};
Cheese::Cheese(char const * b) { // constructor definition
_brand = new char[strlen(b)+1];
strcpy(_brand, b);
}
Cheese::~Cheese() { // destructor definition
if (_brand != nullptr) // if you add another constructor that doesn't set _brand, make sure to set _brand to nullptr
delete _brand; // if we don't free here there's a memory leak
}
char * Cheese::getBrand() {
return _brand;
}
int main(int argc, const char * argv[]) {
const char * brand = "Cabot";
Cheese * cheddar = new Cheese(brand);
std::cout << cheddar -> getBrand();
delete cheddar;
return 0;
}
智能指针#include <iostream>
#include <cstring>
#include <memory>
class Cheese {
std::unique_ptr<char> _brand;
public:
Cheese(const char *); // constructor declaration
char * getBrand();
};
Cheese::Cheese(char const * b) { // constructor definition
_brand = new char[strlen(b)+1]; // smart pointer will free any memory assigned to it on destruction
strcpy(_brand, b);
}
char * Cheese::getBrand() {
return _brand.get();
}
int main(int argc, const char * argv[]) {
const char * brand = "Cabot";
Cheese * cheddar = new Cheese(brand);
std::cout << cheddar -> getBrand();
delete cheddar;
return 0;
}
您不能复制数据,因为在您的类声明中,您只是保留了一个指针,但您没有将其设置为指向任何东西。我的意思是,当你调用构造函数时,对象在内存中只有4个字节的大小,它将保存一个指向任何地方的指针。
要解决这个问题,您可以将brand
变量的声明更改为char[]
数组,但这是一个糟糕的解决方案。
- 为什么std::vector和std::valarray初始化构造函数不同
- 初始化构造函数C++中结构的向量
- C++ 中常量属性的初始化构造函数错误
- 不正确的输出和变量未用Eclipse CDT初始化构造函数
- 如何使用嵌套初始化构造函数中的一维向量初始化矩阵
- 如何通过参数初始化构造函数中的数组?
- 是否有理由使用 malloc 初始化构造函数中的指针
- 如何在 c++ 中初始化构造函数中的二维数组
- 为什么初始化构造函数列表参数时会发生异常?
- 无法初始化构造函数
- 初始化构造函数的默认参数的优选方法是什么?
- 在C++17中使用空列表初始化构造函数时发生编译错误
- C++ 初始化构造函数初始化列表中的嵌套结构?
- 初始化构造函数c++中的向量
- g++ (GCC) 4.6.0 我有以下类,我正在尝试初始化构造函数的结构成员初始化列表
- 使用字符串文本初始化构造函数中的 std::array<char,x> 成员。海湾合作委员会错误?
- 初始化构造函数C++中函数的成员指针
- 在c++中初始化构造函数中的静态成员变量时出错
- memset()初始化构造函数中的对象
- 初始化构造函数C++中的成员向量