Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;智能指针:共享指针与共享数据_C++_Qt_Smart Pointers - Fatal编程技术网

C++ C++;智能指针:共享指针与共享数据

C++ C++;智能指针:共享指针与共享数据,c++,qt,smart-pointers,C++,Qt,Smart Pointers,在本文中,一位Qt程序员试图解释Qt实现的不同类型的智能指针。在一开始,他区分了共享数据和共享指针本身: 首先,让我们澄清一件事: 分享是有区别的 指针和共享数据。当你 共享指针的值 指针及其生存期受到保护 通过智能指针类。换句话说 换句话说,指针是不变量。 但是,指向指针的对象 指的是完全在外面 它的控制。我们不知道 对象是否可复制,如果 可转让或不可转让 现在,数据共享涉及到 智能指针类知道一些事情 关于正在共享的数据。事实上 关键是数据是 被分享,我们不在乎如何分享。 指针被使用的事实 共

在本文中,一位Qt程序员试图解释Qt实现的不同类型的智能指针。在一开始,他区分了共享数据和共享指针本身:

首先,让我们澄清一件事: 分享是有区别的 指针和共享数据。当你 共享指针的值 指针及其生存期受到保护 通过智能指针类。换句话说 换句话说,指针是不变量。 但是,指向指针的对象 指的是完全在外面 它的控制。我们不知道 对象是否可复制,如果 可转让或不可转让

现在,数据共享涉及到 智能指针类知道一些事情 关于正在共享的数据。事实上 关键是数据是 被分享,我们不在乎如何分享。 指针被使用的事实 共享数据在任何时候都是无关紧要的 这一点。例如,你不知道 真的关心Qt工具类是如何的吗 隐式共享,是吗?什么 对你来说,重要的是它们是共享的 (从而减少内存消耗)和 他们工作起来好像不是

坦率地说,我只是不理解这个解释。文章评论中有一个澄清请求,但我认为作者的解释不够充分

如果你明白这一点,请解释。这个区别是什么,以及其他共享指针类(即从Boost或新C++标准)如何适合这个分类?< /P>
提前感谢

在第一种情况下,您为指针添加了一个间接级别,这样由智能指针表示的对象将包裹原始指针。只有一个指向对象的指针,包装器的任务是跟踪对原始指针的引用。非常简单的代码可能如下所示:

template<typename T>
struct smart_ptr {
    T    *ptr_to_object;
    int  *ptr_to_ref_count;
};
模板
结构智能ptr{
T*ptr_到_对象;
int*ptr_至参考计数;
};
复制结构时,复制/分配代码必须确保引用计数增加(或在对象被销毁时减少),但指向实际包装对象的指针永远不会更改,只能进行浅层复制。由于结构非常小,所以复制起来既简单又便宜,而且“所要做的”就是操纵引用计数

在第二种情况下,我觉得它更像一个对象存储库。“隐式共享”部分建议您可以通过执行类似于
BarFoo.getFooWidget()
的操作,向框架请求
FooWidget
,即使它看起来像指针(不管是否智能),您返回的是指向新对象的指针,实际上,您得到了一个指向某个对象缓存中保存的现有对象的指针。从这个意义上讲,它可能更类似于通过调用工厂方法获得的类似于单例的对象


至少在我看来,这种区别听起来是这样的,但我可能离目标太远了,我需要谷歌地图来找到回去的路。

在后来的评论中,他稍微澄清了这一点

这是我在第一节中试图理解的要点。当您使用QSharedPointer时,您正在共享指针的所有权。该类仅控制和处理指针-其他任何内容(如对数据的访问)都超出其范围。当您使用QSharedDataPointer时,您正在共享数据。这个类是为了隐式共享:所以它可能会被拆分

试图解释:

需要注意的是,“指针”在本例中不是指存储地址的对象,而是指对象所在的存储位置(地址本身)。所以严格地说,我认为,你必须说你正在分享这个地址<因此,code>boost::shared_ptr是一个共享“指针”的智能指针
boost::intrusive_ptr
或另一个intrusive智能指针似乎也共享该指针,尽管知道指向的对象的一些信息(它有一个引用计数成员或函数递增/递减)

示例:如果有人与您共享一个黑匣子,但他不知道黑匣子中有什么,这类似于共享指针(代表该黑匣子),但不共享数据(黑匣子中有什么)。事实上,你甚至不知道盒子里的东西是可以共享的(如果盒子里什么都没有怎么办?)。智能指针由您和另一个人表示(当然,您没有共享),但地址是框,它是共享的

共享数据意味着智能指针充分了解指向的数据,因此可能会更改指向的地址(这需要复制数据等)。因此,指针现在可能指向不同的地址。由于地址不同,因此不再共享地址。这也是
std::string
在某些实现中所做的:

std::string a("foo"), b(a);
 // a and b may point to the same storage by now.
std::cout << (void*)a.c_str(), (void*)b.c_str();
 // but now, since you could modify data, they will
 // be different
std::cout << (void*)&a[0], (void*)&b[0];
std::字符串a(“foo”),b(a); //a和b现在可能指向同一个存储器。 我们可以说我们上过这门课吗

struct BigArray{
   int  operator[](size_t i)const{return m_data[i];}
   int& operator[](size_t i){return m_data[i];}
private:
   int m_data[10000000];
};
现在假设我们有两个例子:

BigArray a;
a[0]=1;//initializaation etc
BigArray b=a;
在这一点上,我们需要这个不变量

assert(a[0]==b[0]);
默认的复制ctor可确保此不变量,但代价是深度复制整个对象。我们可以尝试这样的加速

struct BigArray{
   BigArray():m_data(new int[10000000]){}
   int  operator[](size_t i)const{return (*m_data)[i];}
   int& operator[](size_t i){return (*m_data)[i];}
private:
   shared_ptr<int> m_data;
};
现在,我们希望它的工作原理与深度复制案例相同 断言(a[0]!=b[0]); 但它失败了。为了解决这个问题,我们需要一个小小的改变:

struct BigArray{
       BigArray():m_data(new int[10000000]){}
       int  operator[](size_t i)const{return (*m_data)[i];}
       int& operator[](size_t i){
          if(!m_data.unique()){//"detach"
            shared_ptr<int> _tmp(new int[10000000]);
            memcpy(_tmp.get(),m_data.get(),10000000);
            m_data=_tmp;
          }
          return (*m_data)[i];
       }
    private:
       shared_ptr<int> m_data;
    };

这项技术是Cop-Ow(拷贝到写),自C++诞生以来一直存在。它也是非常脆弱的——上面的例子似乎很有效,因为它很小,并且很少有用例。在实践中,很少值得这么麻烦,事实上C++0x已经弃用了COW字符串。所以要小心使用

Qt这个东西仍然让我困惑:)那么你是在暗示他共享数据的意思是COW,共享指针的意思是简单的共享\u ptr/
struct BigArray{
       BigArray():m_data(new int[10000000]){}
       int  operator[](size_t i)const{return (*m_data)[i];}
       int& operator[](size_t i){
          if(!m_data.unique()){//"detach"
            shared_ptr<int> _tmp(new int[10000000]);
            memcpy(_tmp.get(),m_data.get(),10000000);
            m_data=_tmp;
          }
          return (*m_data)[i];
       }
    private:
       shared_ptr<int> m_data;
    };
BigArray b=a;//shallow copy
assert(a==b);//true
b[0]=a[0]+1;//deep copy
b[0]=a[0];//put it back
assert(a==b);//true