我有这段代码:
class MyClass{
public:
string myString;
MyClass(char *aString){
this->myString = std::string(aString);
}
}
int main(){
MyClass example = MyClass("Hi!");
printf("%s\n", example.myString.c_str());
return 0;
}
使用valgrind进行测试显示没有问题,但我无法理解为什么我可以避免使用new来创建字符串副本。
构造函数执行结束后不应该#t; #my; this.myString"在堆栈中丢失?
我不应该要求那段记忆吗?为什么呢?
编辑: 我相信我会因为做我会考虑的事情而感到困惑"相当于"在C中,使用valgrind进行测试会导致错误:
typedef struct MyStruct{
char *p;
}MyStruct_t;
void createMyStruct(MyStruct_t *aStruct, char *text){
char str[10];
strcpy(str,text);
aStruct->p = str;
}
int main(){
MyStruct_t example;
createMyStruct(&example, "Hi!");
printf("%s\n", example.p);
return 0;
}
我出错了什么?
答案 0 :(得分:2)
这是一个错误:
this.myString = std::string(aString);
应该是this->myString
。 (我听说有一个编译器在指针上使用.
实现扩展... uggh)
无论如何,这一行的影响是:
std::string
类型的临时对象,通过将aString
传递给其构造函数进行初始化。该构造函数从char *
复制到std::string
构造函数在临时对象中分配的内存中。 std::string
对象内部包含指向某个已分配存储的指针;在此步骤之后,它不再引用您的字符串文字。this->myString::operator=(std::string const &)
,临时对象绑定到const引用。 std::string::operator=
函数增加目标字符串中的内存分配,并从源字符串复制字节。 (它没有"分享"分配或任何东西)。std::string
的析构函数删除指向其存储区的指针以获取字符串内容。)最终结果是字符串内容按值复制到myString
,没有内存泄漏。在第2步之后,内存中短暂地存在两个字符串内容。
请注意,编译器可能会优化此过程的所有阶段,因此,如果您检查生成的程序集,它可能看起来不同。但从概念上讲,这是已定义的步骤列表。
我猜你可能来自Java ......如果是这样,C ++对所有数据类型都有自动分配(而Java只为原始类型提供它)。您可以在任何您喜欢的地方T(args)
,并创建一个临时T,直到创建它的完整表达式结束。
答案 1 :(得分:1)
回答你的编辑,这实际上是与原文完全不同的问题。
在此代码中:
void createMyStruct(MyStruct_t aStruct, char *text);
MyStruct_t example;
createMyStruct(example, "Hi!");
您将example
按值传递给createMyStruct
。 example
被复制(由于您没有为MyStruct_t
正确定义复制构造函数等,因此具有伪造语义),并且该函数的更改对example
没有影响。
让我们说相反,你决定通过引用传递:
void createMyStruct(MyStruct_t &aStruct, char *text){
char str[10];
strcpy(str,text);
aStruct->p = str;
}
在此代码中,str
是createMyStruct
中的本地字符数组。 createMyStruct
结束后不再存在。
退出此功能后,aStruct->p
(即example.p
)是一个狂野指针。
string
案件中没有发生过这样的情况,甚至没有发生。
如果你写的是char *str = malloc(10);
而不是char str[10];
,那么它会更像原始示例。
std::string
类管理字符串数据的存储。它并没有指向一些外部字符数组。
答案 2 :(得分:0)
我认为你应该理解C ++中的this
关键字。
关键字this标识一种特殊类型的指针。假设 你创建了一个名为x的A类对象,而A类有一个非静态对象 成员函数f()。如果调用函数x.f(),则关键字为this 在f()的主体中存储x的地址。你不能申报 这个指针或对其进行赋值。
所以你应该使用
MyClass(char *aString)
{
this->myString = std::string(aString); // there is no need to use this
}