【问题标题】:c++ copy control issuec ++复制控制问题
【发布时间】:2015-10-18 06:14:30
【问题描述】:
#include <iostream>
#include <string>
#include <vector>
using namespace std;

class HasPtr{
 public:
    //constructor accepts a string
    HasPtr(const string &s = string()) : ps(new string(s)), i(0), use(new size_t(1)) {}  
    //copy constructor
    HasPtr(const HasPtr &h) : ps(h.ps), i(h.i), use(h.use) { ++*use; }
    //copy assignment operator 
    HasPtr &operator=(const HasPtr &h)
    {
        ++*h.use;
        if(--*use == 0)
        {
            delete ps;
            delete use;
        }
        ps = h.ps;
        i = h.i;
        use = h.use;

        return *this;
    }
    ~HasPtr()
    {
        if(--*use == 0)
        {
            delete ps;
            delete use;
        }
    }

//private:
    string *ps;
    int i;

    size_t *use;
};


int main()
{
    HasPtr h("hi mom");
    HasPtr h2 = h;
    HasPtr h3("hi dad");
    h2 = h3;

    cout << "h: " << *h.ps << endl;
    cout << "h2: " << *h2.ps << endl;
    cout << "h3: " << *h3.ps << endl;
}

输出为:

h: hi mom
h2: hi dad
h3: hi dad

我认为输出应该是:

h: hi dad
h2: hi dad
h3: hi dad

我认为输出应该如上的原因:

h 是“嗨妈妈”,h2 共享 h1,所以 h2 是“嗨妈妈”,h3 是“嗨爸爸”,我认为 h2 = h3 更改了 h1 或者因为 h2 共享 h1,但事实并非如此。

我做错了什么?

【问题讨论】:

  • What am I doing wrong?:使用指针。如果你使用对象,这一切都会消失。还有一个引用计数的智能指针std::shared_ptr
  • h2 = h3 根本不影响h1。您不是在修改指向的内容,而是存储在h2 中的指针。比较:coliru.stacked-crooked.com/a/c380c6c80e66a393
  • 为了将来参考,您可能想了解copy and swap idiomthe Big Three。正如@LokiAstari 所说,您可能还只想使用内置的std::shared_ptr
  • h2 共享 h1,直到您分配给 h2 为止。这是经典的引用计数 - 语义就像您在处理简单的值对象一样,但副本被推迟到真正需要它们时。一个好主意,但在实践中并不是一个胜利,特别是如果您使用多个线程。

标签: c++ string pointers c++11


【解决方案1】:

这是怎么回事:

HasPtr h("hi mom");
HasPtr h2 = h;

h.ps ---> "hi mom"  <--- h2.ps

然后在下一条语句中,您更改h2,但这不会影响h

HasPtr h3("hi dad");
h2 = h3;

h2.ps ----> "hi dad" <--- h3.ps
 |
XXX changed
 |
"hi mom" <--- h.ps

指针是指向同一地址的不同实例。示例:

int a = 5, c = 1; 
int *p1 = &a, *p2 = &a;

更改p1(即p1 = &amp;c)不会影响p2

【讨论】:

  • 还是不明白。 h2 与 h1 具有相同的指针。如果 h2 改变了,为什么 h1 不改变?
  • @XIAODI 指针是指向同一个地址的不同实例。示例:int a = 5; int *p1 = &amp;a, *p2 = &amp;a。更改p1(即p1 = &amp;c)不会影响p2
【解决方案2】:

让我们考虑一个简化的例子会更清楚

int x = 10;
int y = 20;

int *h = &x;
int *h2 = h;

现在hh2 指向x。您可以检查此输出指针指向的对象。例如

std::cout << "*h = " << *h << ", *h2 = " << *h2 << std::endl;

那么你使用的是第三个指针

int *h3 = &y;
h2 = h3;

现在h2h3 指向yh 没有改变。你也可以看看这个

std::cout << "*h2 = " << *h2 << ", *h3 = " << *h3 << std::endl;
std::cout << "*h = " << *h << std::endl;

语句中的对象也是如此

HasPtr h("hi mom");
HasPtr h2 = h;
HasPtr h3("hi dad");
h2 = h3;

只有对应的指针(ps)被包裹在类的对象中。

这是一个演示解释的程序

#include <iostream>
#include <string>


int main()
{
    std::string hi_mom( "hi mom" );
    std::string hi_dad( "hi dad" );

    std::string *h  = &hi_mom;
    std::string *h2 = h;

    std::cout << "*h = " << *h << ", *h2 = " << *h2 << std::endl;

    std::string *h3 = &hi_dad;
    h2 = h3;

    std::cout << "*h2 = " << *h2 << ", *h3 = " << *h3 << std::endl;
    std::cout << "*h = " << *h << std::endl;
}        

它的输出是

*h = hi mom, *h2 = hi mom
*h2 = hi dad, *h3 = hi dad
*h = hi mom

【讨论】:

  • 谢谢,能给我一个对应指针的例子吗?
  • @XIAOD "对应指针"是数据成员 ps 声明为字符串 *ps;对应的对象 h、h2 和 h3。事实上,这个类只是这个指针的一个包装器,在我的例子中,我删除了包装器,只留下指针本身,并以与对象名称相同的方式命名它们。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-09-27
  • 2013-01-27
  • 2015-06-23
  • 2022-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多