自定义容器适用于 g++(Rstudio),不适用于 MSVS 2012

Customized container works fine with g++(Rstudio), not fine with MSVS 2012

我有一段 C++ 测试代码在 Rstudio 中运行良好,它使用 g++,但在 MSVS 2012 中会导致 运行 次错误:

template<typename T>
struct vec{
    T*head, *tail;
    vec()
    {
        head=NULL;
        tail=NULL;
    }
    vec(int n)
    {
        head=(T*)malloc(sizeof(T)*n);
        tail=head+n;
    }
    T operator [] (int i) const {return *(head+i);}
    T & operator [] (int i) {return *(head+i);}
    ~vec(){free(head);}
};

int main(){
    std::vector<int>y(3);
    y[0]=1; y[1]=2; y[2]=3;
    vec<int>x1(3);
    x1[0]=y[0];
    std::cout<<"vec of integers, [] overloading works fine \n";
    std::vector<std::vector<int>::iterator>z(3);
    z[0]=y.begin();
    z[1]=y.begin()+1;
    z[2]=y.begin()+2;
    vec<std::vector<int>::iterator>x2(3);
    x2[0]=z[0];
    std::cout<<*x2[0]<<"\n";
    std::cout<<"vec of std::vector::iterator, [] overloading g++ works fine, MSVS doesn't \n";
    return 1;
}

代码显示如果vec包含整数,MSVS和Rstudio都可以正常工作;如果 vec 包含迭代器,MSVS 将 运行 出现以下错误:

我感觉到它与迭代器有关。谁能让我知道我的错误在哪里?顺便说一句,我只在 MSVS 中包含了矢量头文件。

谢谢!

VS 在调试模式下的迭代器中内置了额外的错误检查。它在您的代码中发现了一个合法的错误!错误是您将未初始化的内存重新解释为已初始化的对象:

vec(int n){head=(T*)malloc(sizeof(T)*n);tail=head+n;}
                ^^^^^^^^^^^^^^^^^^^^^^^

T & operator [] (int i) {return *(head+i);}
                                ^^^^^^^^^

x2[0]=z[0];
^^^^^^

赋值在矢量迭代器对象上调用 operator=,它实际上是未初始化的内存,当它试图将部分内存解释为有效数据时会导致您看到的崩溃。 (顺便说一句,0xCDCDCDCD 是调试器通常用来填充未初始化内存的内容,以帮助更快地捕获此类错误。)

我建议使用 new/delete 而不是 malloc。在 C++ 中很难正确分配原始内存(普通内存管理已经够难了)。

另请注意,在一般情况下,malloc 可能不会为所有对象类型生成具有足够高对齐度的块(尽管大多数情况下会这样,因为很少有对象对齐到超过 16 个字节).

您正在使用 malloc 分配(未初始化的)内存,并试图将其解释为像迭代器那样的非 POD 类型。这注定会失败 - operator= 一个对象需要一个初始化的对象作为它的左操作数,但是你给它一个垃圾值(因此崩溃)。

此外,您没有调用元素的析构函数,因为您使用的是普通 free

一个简单的解决方案是在构造函数中使用 new T[n] 而不是 malloc(在析构函数中使用 delete[])。这要求您的 T 是可默认构造的;有一些方法可以削弱这个要求(包括放置 new 和一些保证对齐的技巧)。

顺便说一句,你的 vec class 既没有实现 "rule of three" 也没有实现 "rule of five",既没有禁用复制构造,所以你将有双如果您的 vec 对象被复制,则释放。