【问题标题】:C++ Dynamic array has not requested sizeC++ 动态数组没有请求大小
【发布时间】:2021-10-13 09:10:07
【问题描述】:

在为 STL Multimap 创建自定义类时,我遇到了一种意外行为,即由 new 运算符创建的动态数组的大小不在 [] 之间。在下面的代码中,在a.Set(3, 'c') 中,存储在newKeynewSize 中的数组大小为1,而它们的大小应该为2。使用调试器显示,在那行中index 等于 1,所以大小应该是 2。程序不会产生任何异常,但也不会输出预期的结果c

作为澄清,使用调试器表明在newKey, newSize, newValue 的索引 1 处设置值时会出现问题。它不会抛出任何异常,但也不会改变任何值。

template<typename T>
void Copy(T const* _source, T* _destiny, unsigned long _size)
{
    for (unsigned long i = 0; i < _size; i++)
    {
        _destiny[i] = _source[i];
    }
}
template<typename T>
void CopyNew(T const* _source, T* _destiny, unsigned long _size)
{
    T* target = new T[_size];
    for (unsigned long i = 0; i < _size; i++)
    {
        target[i] = _source[i];
    }
    _destiny = target;
}

template<typename T1, typename T2>
class Multimap
{
public:
    Multimap() {}
    unsigned long Get(T1 const& _key, T2** _return)
    {
        for (unsigned long i = 0; i < this->keySize_; i++)
        {
            if (_key == this->key_[i])
            {
                CopyNew<T2>(this->value_[i], *_return, this->valueSize_[i]);
                return i;
            }
        }
        *_return = 0;
        return this->keySize_;
    }
    unsigned long Get(T1 const& _key)
    {
        for (unsigned long i = 0; i < this->keySize_; i++)
        {
            if (_key == this->key_[i])
            {
                return i;
            }
        }
        return this->keySize_;    
    }
    int Set(T1 const& _key, T2 const& _value)
    {
        T2* target;
        unsigned long index = this->Get(_key, &target);
        if (target == 0)
        {
            T1* newKey = new T1[index + 1];
            unsigned long* newSize = new unsigned long[index + 1];
            T2** newValue = new T2*[this->keySize_ + 1];
            if (this->keySize_ != 0)
            {
                Copy(this->key_, newKey, index);
                delete[] this->key_;
                Copy(this->valueSize_, newSize, index);
                for (unsigned long i = 0; i < this->keySize_; i++)
                {
                    newValue[i] = new T2[this->valueSize_[i]];
                    Copy(this->value_[i], newValue[i], this->valueSize_[i]);
                    delete[] this->value_[i];
                }
                delete[] this->valueSize_;
            }
            newKey[index] = _key;
            newSize[index] = 0;
            this->key_ = newKey;
            this->valueSize_ = newSize;
            this->value_ = newValue;
            this->keySize_++;
        }
        unsigned long newSize = this->valueSize_[index]+1;
        T2* newValue = new T2[newSize];
        Copy(this->value_[index], newValue, newSize-1);
        newValue[newSize-1] = _value;
        this->valueSize_[index] = newSize;
        this->value_[index] = newValue;
        return newSize;
    }
    unsigned int GetSize()
    {
        return this->keySize_;
    }
protected:
    unsigned long keySize_ = 0;
    unsigned long* valueSize_ = 0;
    T1* key_ = 0;
    T2** value_ = 0;
};

int main()
{
    Multimap<int, char> a;
    a.Set(2, 'b');
    a.Set(3, 'c');
    char* b;
    a.Get(3, &b);
    std::cout << b[0];
}

【问题讨论】:

  • 检查使用-g -fsanitize=address,undefinedrun tine program 编译时会发生什么。不相关:“_destiny”应该是“_destination”。
  • 旁注:明确使用newdelete,因为C++11 被认为是一种不好的做法。使用std::vector 或智能指针。这比学习如何编写自己的模板更重要。
  • CopyNew 的人不明白参数是如何按值传递的,除非指定为引用类型。 _destiny = target;CopyNew 的调用者意味着 nothing。无论作为_destiny 参数提供给CopyNew 的任何内容都将保持原样(作为奖励,CopyNew 因此会泄漏内存以在伤口中添加盐)。
  • @MarekR 但我听说使用任何 STL 类或函数都是不好的做法,因为如果在 DLL 中使用,使用 DLL 的人的 STL 版本可能与用于编译 DLL 的版本不同。 .
  • 然后你的DLL被编译器Q编译的程序调用。Q使用不同的后端魔法,它发送给你的DLL的X实例是不同的形状。卡繁荣。这对您来说可能不是问题。也许您只支持一种编译器和一种编译器版本。否则你的界面只需要处理我们过去称为普通旧数据的简单类型,Standard Layout.

标签: c++ gcc visual-studio-code


【解决方案1】:

CopyNew 参数 _destiny 应该是 T*&amp;(正如 WhozCraig 在 cmets 中指出的那样)。否则,函数会更改参数,但不会更改传递给函数的变量。为了更改变量,您必须取消引用参数,因此它的类型必须是指针或对变量类型的引用。由于变量的类型是T*,所以参数类型应该是T**或者T*&amp;

【讨论】:

    猜你喜欢
    • 2011-05-03
    • 1970-01-01
    • 2011-10-24
    • 2014-02-23
    • 2014-11-15
    • 2020-11-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多