C++ 初始化带有本地对象的向量时出错

C++ 初始化带有本地对象的向量时出错,c++,pointers,vector,c++11,C++,Pointers,Vector,C++11,我想用不同类型的对象创建一个向量,但是 此代码引发以下异常: free():无效指针:0x0000000000401757*** #include <vector> class A { char * elem; public: A() { elem = new char[10]; } void setA(char* name) { elem = name; } ~A() {

我想用不同类型的对象创建一个向量,但是

此代码引发以下异常: free():无效指针:0x0000000000401757***

#include <vector>

class A
{
    char * elem;

public:
    A()
    {
        elem = new char[10];
    }
    void setA(char* name)
    {
        elem = name;
    }
    ~A()
    {
        delete[] elem;
    }

};

int main(int argc, char **argv)
{
    std::vector<A> v_a;
    for (int i = 0; i < 10; ++i)
    {
        A m_a;
        m_a.setA("jaja");
        v_a.push_back(m_a);

    }
}
#包括
甲级
{
char*elem;
公众:
()
{
elem=新字符[10];
}
无效setA(字符*名称)
{
elem=名称;
}
~A()
{
删除[]项;
}
};
int main(int argc,字符**argv)
{
std::向量v_a;
对于(int i=0;i<10;++i)
{
A m_A;
m_a.setA(“jaja”);
v_a.推回(m_a);
}
}

为什么会发生这种情况??如何实现正确的解决方案?

您可以修改
elem
的值,该值是指向空闲存储区上分配的内存区域的指针。现在,
elem
指向一个字符串文本,它不适用于
delete
delete[]

delete
ing不在免费存储中的对象是未定义的行为。尽管如此,析构函数仍会尝试执行此操作。

调用
setA(…)
时,您没有复制字符串的数据,而是复制本地字符串的地址。(检查有关指针和字符串文字的说明)

在使用
setA(…)
调用的块结束后,此字符串超出范围,因此其地址在之后无效

因此,您正在尝试从堆栈上分配的析构函数的堆中释放内存,而此时该析构函数早已不存在了

更新建议1:于2016年1月27日添加

  • 另外,在将
    a
    的实例推送到
    std::vector
    时,还需要考虑复制ctor。遵照命令,我还添加了一个复制赋值操作符

    如遇以下情况,请参见

  • 正确处理可能“错误”大小的字符串

    #include <cstring>
    
    ...
    
    /// copy ctor
    A(const A& other) :
            elem(new char[10])
    {
        // prevent duplicate code
        setA(other.elem);
    }
    
    /// copy assignment operator
    A& operator=(const A& other)
    {
        // prevent duplicate code
        setA(other.elem);
    
        return *this;
    }
    
    /// set A's name (which is truncated to 9 characters if necessary)
    void setA(const char* name)
    {
        // copy first 9 chars from name
        // if there's fewer chars: elem is padded with zeros
        std::strncpy(elem, name, 9);
    
        // add null character / zero (string delimiter) manually
        // this is necessary for cases where name has 10 or more chars
        elem[9] = 0;
    }
    

<强>建议2:切换到C++风格字符串

  • 使用
    std::string
    (我更喜欢这个版本,因为它省去了内存处理,而且读取起来非常直观)

    #包括
    甲级
    {
    字符串元素;
    公众:
    A(){}
    void setA(std::string name)
    {
    elem=名称;
    }
    ~A(){}
    };
    

您是否尝试过使用调试器来查找程序中失败的点?谢谢您的回答,我正被迫使用char*所以建议1对我有效,只做了一个更改。我必须添加复制构造函数,因为类型为A.A(const A&other)的对象的向量if{elem=new char[10];std::memcpy(elem,other.elem,10);}我添加了建议1的改进版本。在处理不同(或错误)大小的字符串时,您可能会考虑使用它来增强鲁棒性。
#include <cstring>

...

void setA(char* name, size_t length)
{
    std::memcpy(elem, name, length);
}
#include <string>

class A
{
    std::string elem;

public:
    A(){}

    void setA(std::string name)
    {
        elem = name;
    }

    ~A(){}
};