Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 传入构造函数的值超出范围后会发生什么情况?_C++_String_Object Lifetime - Fatal编程技术网

C++ 传入构造函数的值超出范围后会发生什么情况?

C++ 传入构造函数的值超出范围后会发生什么情况?,c++,string,object-lifetime,C++,String,Object Lifetime,我一直在寻找这个问题的答案,但没有找到任何与我的问题类似的答案 我有一个类,我们称之为Foo,它在构造函数中接受一个const char*指针。在我的代码中,我需要使用std::string的.data作为参数创建一个新的Foo。问题是,一旦字符串、值或指针超出范围,这就是我感到困惑的地方。。传递给Foo的数据无效 既然字符串无效,那么Foo的const char*就无效了 如何将字符串数据的值传递到Foo中,以便在字符串超出范围时不会失效?如果需要将字符串复制到Foo中以存储它,如果需要,则可

我一直在寻找这个问题的答案,但没有找到任何与我的问题类似的答案

我有一个类,我们称之为Foo,它在构造函数中接受一个const char*指针。在我的代码中,我需要使用std::string的.data作为参数创建一个新的Foo。问题是,一旦字符串、值或指针超出范围,这就是我感到困惑的地方。。传递给Foo的数据无效

既然字符串无效,那么Foo的const char*就无效了


如何将字符串数据的值传递到Foo中,以便在字符串超出范围时不会失效?

如果需要将字符串复制到Foo中以存储它,如果需要,则可能应该将字符串复制到Foo中以存储它。

如果需要,则可能应该将字符串复制到Foo中以存储它最后一次通过构造函数的调用范围。

为什么不复制一个字符串呢?这样你就知道它不会消失。如果你不知道常量字符*在你的类的生命周期中会一直存在,你需要复制它或者做一些不同的事情,比如把字符串包装在引用计数器中,为什么不复制一个字符串呢?这样你就知道它不会消失。如果你不知道const char*在你的类的生命周期中会一直存在,你需要复制它或者做一些不同的事情,比如把字符串包装在一个引用计数器中,仅仅给出描述无助于破译代码中的错误。返回指向字符数组起始字符的指针。只要传递的内存位置没有变为无效,类成员和传递的参数都指向同一位置。如果您看到了这一点,那么传递的参数将超出范围,也就是说,它不再有效,那么您的类成员将成为悬空指针。在这种情况下,最好复制传递的字符串。这应该给你一个想法-

#include <iostream>
#include <string>

class Foo
{
    const char* temp;

    public:
    Foo( const char* temp_ ) : temp(temp_) {}
    void check( )
    {
            while( *temp != '\0' ){
                std::cout << *temp ;
                ++temp;
            }
            std::cout << std::endl;
    }
};

int main()
{
    std::string str = "I am a string";

    Foo *obj = new Foo( str.data() );

    obj->check();
    return 0;
}
输出:我是一个字符串
. 希望这有帮助

仅仅给出描述无助于破译代码中的错误。返回指向字符数组起始字符的指针。只要传递的内存位置没有变为无效,类成员和传递的参数都指向同一位置。如果您看到了这一点,那么传递的参数将超出范围,也就是说,它不再有效,那么您的类成员将成为悬空指针。在这种情况下,最好复制传递的字符串。这应该给你一个想法-

#include <iostream>
#include <string>

class Foo
{
    const char* temp;

    public:
    Foo( const char* temp_ ) : temp(temp_) {}
    void check( )
    {
            while( *temp != '\0' ){
                std::cout << *temp ;
                ++temp;
            }
            std::cout << std::endl;
    }
};

int main()
{
    std::string str = "I am a string";

    Foo *obj = new Foo( str.data() );

    obj->check();
    return 0;
}
输出:我是一个字符串 . 希望这有帮助

您有两个选择:

到目前为止,更简单的选择是将其存储在类中的std::string中。 使用new[]分配您自己的char*,并将数据strcpy到构造函数中的新char*中。然后还需要定义一个析构函数来删除[]Foo的char*。然后,与通常的情况一样,您还需要定义复制构造函数和复制赋值操作符来分配它们自己的新字符*,在复制赋值操作符的情况下,删除[]旧字符*,并从原始Foo复制字符*。很容易犯错误并造成内存泄漏,或者由于尝试访问释放的内存而导致随机崩溃。 x

我很有可能遗漏了什么,因为这是我脑子里想不到的,但我相信有人会在评论中指出这一点

此外,使用Boost提供的共享_ptr可能会使选项2的使用更加方便,但我没有太多的使用经验,仅用于一个小项目可能会有点繁重

还有一条评论。您应该真正使用,也应该反对,因为它会添加所需的空字符。

您有两个选项:

到目前为止,更简单的选择是将其存储在类中的std::string中。 使用new[]分配您自己的char*,并将数据strcpy到构造函数中的新char*中。然后还需要定义一个析构函数来删除[]Foo的char*。然后,与通常的情况一样,您还需要定义复制构造函数和复制赋值操作符来分配它们自己的新字符*,在复制赋值操作符的情况下,删除[]旧字符*,并从原始Foo复制字符*。很容易犯错误并造成内存泄漏,或者由于尝试访问释放的内存而导致随机崩溃。 x

我很有可能遗漏了什么,因为这是我脑子里想不到的,但我相信有人会在评论中指出这一点

此外,使用Boost提供的共享_ptr可能会使选项2的使用更加方便,但我没有太多的使用经验,仅用于一个小项目可能会有点繁重

还有一条评论。你真的应该使用,以及反对,因为它添加了空字符,你将nee
d、 复制它。在refcount友好的语言中,您将保留字符串。但这是C++。如果不复制指针,则存在挂起指针的高风险

class Foo
{
 public:
   Foo(const char*  _data) 
   { 
      mData = new char[strlen(_data) + 1];
      strcpy(mData, _data); 
   }
   Foo& operator=(const Foo& _other) { /* deep copy string */ } 
   Foo(const Foo& _other) { /* deep copy string */ }
   ~Foo() { delete[] mData; }
 private:
   char* mData;
};


如您所见,std::string选项更简单。

复制它。在refcount友好的语言中,您将保留字符串。但这是C++。如果不复制指针,则存在挂起指针的高风险

class Foo
{
 public:
   Foo(const char*  _data) 
   { 
      mData = new char[strlen(_data) + 1];
      strcpy(mData, _data); 
   }
   Foo& operator=(const Foo& _other) { /* deep copy string */ } 
   Foo(const Foo& _other) { /* deep copy string */ }
   ~Foo() { delete[] mData; }
 private:
   char* mData;
};



如您所见,std::string选项更简单。

不,不起作用。在main:str[3]='X';中的新Foo行之后添加此项;。现在看看输出是什么。正在存储的字符串的内部数据的地址将在该字符串被销毁并释放该数据后立即无效,无法访问。问题确实有足够的数据。如果在ctor中向您传递了一个指针,那么如何使用该指针进行操作,以避免获得悬空引用。更好的做法是复制传递的字符串是正确的,答案与前两个相同。这确实帮助我了解指针内部的情况。谢谢@虽然你的问题有足够的数据来说明你在做什么,但是如果实际的代码被发布,很容易看出哪里出了错。欢迎来到指针世界我也在学习指针。不,不行。在main:str[3]='X';中的新Foo行之后添加此项;。现在看看输出是什么。正在存储的字符串的内部数据的地址将在该字符串被销毁并释放该数据后立即无效,无法访问。问题确实有足够的数据。如果在ctor中向您传递了一个指针,那么如何使用该指针进行操作,以避免获得悬空引用。更好的做法是复制传递的字符串是正确的,答案与前两个相同。这确实帮助我了解指针内部的情况。谢谢@虽然你的问题有足够的数据来说明你在做什么,但是如果实际的代码被发布,很容易看出哪里出了错。欢迎来到指针世界我也在学习指针。在看到Rob的答案后,我尝试了类似于您的第一个选项的方法,似乎在目标未初始化的情况下使用std::strcpy给了我一个eror?规则三-您还需要定义复制构造函数和复制赋值运算符,除非您完全100%确定您在任何地方都没有使用它们,并且永远不会使用它们“以后再使用它们。@Matt B:当我第一次发布答案时,我实际上忘记了分配字符数组。”。我编辑了代码。现在应该可以了。user470379是正确的,您需要实现一个复制构造函数和复制赋值操作符,这样当有人将fooA=fooB;设为fooA=fooB;时,它不会对字符串进行浅拷贝;。但是,如果选择std::string选项,则不必这样做。这不仅仅是不创建浅层副本,如果不实现它们并创建副本,然后两个析构函数都会尝试删除相同的内存。在看到Rob的答案后,我尝试了与您的第一个选项类似的方法,似乎在目标未初始化的情况下使用std::strcpy给了我一个三个eror?规则-您还需要定义复制构造函数和复制赋值运算符,除非您完全确定你不会在任何地方使用它们,将来也不会使用它们。@Matt B:我第一次发布答案时,实际上忘记了分配字符数组。我编辑了代码。现在应该可以了。user470379是正确的,您需要实现一个复制构造函数和复制赋值操作符,这样当有人将fooA=fooB;设为fooA=fooB;时,它不会对字符串进行浅拷贝;。如果您选择std::string选项,则不必这样做。这不仅仅是不创建浅层副本,如果您不实现它们并创建副本,那么两个析构函数都会尝试删除相同的内存。将其存储为字符串似乎简单得多,我会尝试,谢谢!将其存储为字符串似乎不那么复杂,我会尝试一下,谢谢!
class Foo
{
 public:
   Foo(const std::string& _data) : mData(_data) { }
 private:
   std::string mData;
};