修复了双重免费或损坏错误,但为什么会出现错误?

时间:2017-08-22 18:29:20

标签: c++ pass-by-reference dynamic-memory-allocation

我有以下代码:

src/main.cpp

#include <include/array.hpp>

int main() {
    int temp[] = {1, 2, 3, 4, 5};
    sdizo::array<int> a(temp, 5);
    print_array(a);
    return 0;
}

include/array.hpp

#pragma once
#include <string.h>
#include <iostream>

namespace sdizo {

template <class T>
class array {
private:
    T* data;
    int length;

public:
    array();
    array(T* d, int len);
    ~array();
    T* begin();
    T* end();
};
template <typename T>
array<T>::array() {
    data = nullptr;
    length = 0;
}

template <typename T>
array<T>::array(T* d, int len) {
    length = len;
    this->data = new T[len];
    memcpy(this->data, d, sizeof(d[0]) * len);
}
template <typename T>
array<T>::~array() {
    delete[] this->data;
}
template <typename T>
T* array<T>::begin() {
    return &data[0];
}
template <typename T>
T* array<T>::end() {
    return &data[length];
}

template <typename T>
void print_array(array<T> ar) {
    for (auto x : ar) {
        std::cout << x << " ";
    }
    std::cout << '\n';
}
}

使用以下内容进行编译:{{1​​}}

现在运行它会出现以下错误:

enter image description here

我注意到当我没有打印数组时,没有发生错误。我想通过引用传递数组,因为现在它会创建一个本地副本,可能错误是由于调用析构函数两次引起的。因此g++ src/*.cpp -I./ -std=c++1z -g -o bin/sdizo1代替void print_array(array<T> &ar)工作。

问题现在已经消失,但为什么会这样。我知道可能void print_array(array<T> ar)在同一个内存位置被调用了两次,或类似的东西,但为什么呢。 C ++编译器不够智能,无法检测到那些东西吗?或者我应该总是通过引用传递,还是有一种方法来传递值,而不是通过自定义析构函数的结构接收那些错误?

我知道对于许多比我更聪明的人来说可能会很无聊,但是嘿,他没有任何疑问,没有任何学习。

1 个答案:

答案 0 :(得分:5)

rule of three/five/zero。你有一个带有原始拥有指针的类。您的默认复制构造函数和复制赋值运算符将不会执行您所期望的操作,它们仅复制指针。两个或多个实例具有指向相同数据的指针,每个实例都删除它。

编辑:为了澄清,当您通过引用更改print_array以获取其参数时,您没有发现问题的原因是您不会使用有缺陷的复制构造函数或复制赋值运算符。这不是print_array的问题,它是必须纠正的array类中的缺陷。