Qt C++11 从 QList 分发原始指针

问题描述

我正在解决一个问题,我有某种定制的“容器”DTO,其中包含一系列项目。该类的用户应该能够从容器中的某个位置检索项目。我希望容器不要保留指向它包含的项目的原始指针的引用,而是真正拥有它们,因此不需要自定义析构函数。这是我想出的:

#include <QList>

class MyItem {

public:
    MyItem(int n) : number(n){}

private:
    int number;
};

class MyContainer {

public:
    void addItem(MyItem item){
        m_items.append(item);
    }

    MyItem* getItemAt(int pos){
           if(pos < m_items.size() && pos >= 0){
                return &(m_items.at(pos));
           }
           return nullptr;
    }

private:
    QList<MyItem> m_items;

};


int main(){

    MyContainer container;

    MyItem item1(4);
    container.addItem(item1);

    MyItem* item_ptr = container.getItemAt(0);
    return 0;
}

getItemAt 函数的返回中,我收到此错误

main.cpp:21:24: error: cannot initialize return object of type 'MyItem *' with an rvalue of type 'const MyItem *'

我的函数需要返回一个非常量的值,因为调用者需要修改检索到的对象。有没有办法来解决这个问题?这是避免析构函数并向调用者指示返回值为空的最佳解决方案吗。

我知道有几种方法可以做到这一点:

  • 返回一个可选的:不幸的是我必须使用 C++11 所以不是一个选项
  • 抛出异常:我真的不喜欢这个选项,因为代码库有 0 个 atm 异常,我宁愿不在这里介绍它们。

解决方法

返回指向 QList 存储中的内存地址的指针是不明智的。从 QList 文档中“请注意,在 QList 上执行的任何非常量函数调用都会使所有现有的迭代器未定义”。如果内部容器存储了实际的指针,那么这将不是问题。这些甚至可以是无需编写析构函数的智能指针。

但是我也看到您通过值传递来添加项目。如果按值传递在那里是可以接受的,那么为什么不返回呢?这是一个不一致的界面。

听起来你真的想通过引用传递和返回,例如add(const MyItem&)MyItem& get(int)

如 rafix 所述,QList 的 operator[](idx) 返回一个非常量引用,因此您可以简单地返回该引用。

那你将如何进行边界检查?有多种方法,但最简单的方法是添加一个 size() 方法。