课堂内没有记忆丧失

时间:2014-04-04 03:18:57

标签: c++

我有这段代码:

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;
}

我出错了什么?

3 个答案:

答案 0 :(得分:2)

这是一个错误:

this.myString = std::string(aString);

应该是this->myString。 (我听说有一个编译器在指针上使用.实现扩展... uggh)

无论如何,这一行的影响是:

  1. 创建std::string类型的临时对象,通过将aString传递给其构造函数进行初始化。该构造函数从char *复制到std::string构造函数在临时对象中分配的内存中。 std::string对象内部包含指向某个已分配存储的指针;在此步骤之后,它不再引用您的字符串文字。
  2. 调用this->myString::operator=(std::string const &),临时对象绑定到const引用。 std::string::operator=函数增加目标字符串中的内存分配,并从源字符串复制字节。 (它没有"分享"分配或任何东西)。
  3. 破坏临时对象(并且std::string的析构函数删除指向其存储区的指针以获取字符串内容。)
  4. 最终结果是字符串内容按值复制到myString,没有内存泄漏。在第2步之后,内存中短暂地存在两个字符串内容。

    请注意,编译器可能会优化此过程的所有阶段,因此,如果您检查生成的程序集,它可能看起来不同。但从概念上讲,这是已定义的步骤列表。

    我猜你可能来自Java ......如果是这样,C ++对所有数据类型都有自动分配(而Java只为原始类型提供它)。您可以在任何您喜欢的地方T(args),并创建一个临时T,直到创建它的完整表达式结束。

答案 1 :(得分:1)

回答你的编辑,这实际上是与原文完全不同的问题。

在此代码中:

void createMyStruct(MyStruct_t aStruct, char *text);

MyStruct_t example;
createMyStruct(example, "Hi!");

您将example 按值传递给createMyStructexample被复制(由于您没有为MyStruct_t正确定义复制构造函数等,因此具有伪造语义),并且该函数的更改对example没有影响。

让我们说相反,你决定通过引用传递:

void createMyStruct(MyStruct_t &aStruct, char *text){
   char str[10];
   strcpy(str,text);
   aStruct->p = str;
}

在此代码中,strcreateMyStruct中的本地字符数组。 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
}