【问题标题】:Calling std::swap in shared pointers' values call a bunch of constructors and destructors在共享指针的值中调用 std::swap 会调用一堆构造函数和析构函数
【发布时间】:2018-08-12 05:17:45
【问题描述】:

我最近开始学习移动语义和共享指针,但我很难理解它。

我目前正在学习关于这些主题的课程,但是讲师没有解释为什么当我们交换指针中包含的值时会调用这些构造函数和析构函数。共享指针中交换的调用(如 b.swap(a) 和 std::swap(a, b) 不调用任何构造函数或析构函数,而调用 std::swap(*a, * b) 打电话给他们。

主要代码:

int main(int argc, char** argv){

    std::shared_ptr<strc> a = std::make_shared<strc>("one");
    std::shared_ptr<strc> b = std::make_shared<strc>("two");

    message("b.swap(a)"); // No constructors or destructors are called.
    b.swap(a);
    disp(a);
    disp(b);

    message("std::swap"); // A bunch of constructors and destructors are called.
    std::swap(*a, *b);
    disp(a);
    disp(b);

    message("std::swap"); // No constructor or destructors are called.
    std::swap(a, b);
    disp(a);
    disp(b);

    return 0;
}

“strc”的实现类是(为了简洁起见,我将在其中展示“重要”实现):

strc::strc(strc && o){
    msg("Move Constructor.");
    this->data = std::move(o.data);
    o.data = nullptr;
}

strc::~strc(){
    msg("Destructor.");
    delete [] data;
}

strc & strc::operator = (strc o){
    msg("Copy and Swap (=).");
    swap(o);
    return *this;
}

void strc::swap(strc & o){
    msg("Calling std::swap");
    std::swap(this->data, o.data);
}

这是打印到控制台的内容(让我更多地了解正在发生的事情并彻底了解移动语义和共享指针)。

调用 b.swap(a) 一 (1) 两(1)个

调用 std::swap(*a, *b) strc:移动构造函数。 strc:移动构造函数。 strc:复制和交换(=)。 strc: 调用 std::swap strc:析构函数。 strc:移动构造函数。 strc:复制和交换(=)。 strc: 调用 std::swap strc:析构函数。 strc:析构函数。 两 (1) 一(1)个

调用 std::swap(a, b) 一 (1) 两(1)个

这是为什么呢?它与移动语义有关吗?它不应该调用标准交换函数吗?我无法理解这些交换调用之间的区别,以及为什么其中一个调用所有这些构造函数和析构函数。

【问题讨论】:

  • 如果您尝试自己编写一个 shared_ptr 类会有所帮助。这可能会更明显地说明为什么在调用 swap(*a,*b) 时,周围的 shared_ptr 是无关紧要的。

标签: c++ c++11 shared-ptr move-semantics


【解决方案1】:
  1. b.swap(a) 交换指针。
  2. std::swap(*a, *b) 交换指向对象的内容。
  3. std::swap(a, b) 再次交换指针。

在案例 2 中使用了移动构造函数。这就是它们的用途。

在情况 1 和 3 中也使用了移动构造函数,但您没有观察到这一点,因为您没有修改 std::shared_ptr 构造函数。

您可以在这里了解更多信息Should the Copy-and-Swap Idiom become the Copy-and-Move Idiom in C++11?

【讨论】:

  • 我明白你的意思了!就我在控制台中的内容而言:调用了两个移动构造函数。这意味着为交换功能制作了两个副本,对吗?然后,它打印“复制和交换 (=)”。这是为什么?为什么我的 '=' 重载函数被调用?在它之后,调用单个析构函数。我无法清楚地理解幕后发生的事情。调用这个单一的析构函数后,又调用了另一个移动构造函数,然后再次打印“Copy and Swap(=)”,并删除了另外两个析构函数。
  • 阅读这篇文章stackoverflow.com/questions/25286544/…你没有提供移动赋值操作符,t1 = t2 = 使用通用赋值操作符。移动构造函数仅用于t1 = std::move(t2)
猜你喜欢
  • 1970-01-01
  • 2012-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-16
  • 2023-03-11
  • 2013-04-14
相关资源
最近更新 更多