C++移动语义和函数调用[已关闭]

polhcujo  于 2023-02-20  发布在  其他
关注(0)|答案(1)|浏览(147)
    • 已关闭**。此问题需要超过focused。当前不接受答案。
    • 想要改进此问题吗?**更新此问题,使其仅关注editing this post的一个问题。

8小时前关门了。
Improve this question
我正在刷新我的C++技能,重新学习移动语义。以下是我无法理解的示例程序和输出。

#include <iostream>
#include <iomanip>

int sepI = 0;
void printSep(const char* msg) {
    std::cout
        << std::setw(40) << std::setfill('>') << "" << std::setfill(' ')
        << std::setw(2) << std::setiosflags(std::ios::right) << sepI++ << ": " << std::resetiosflags(std::ios::right)
        << std::setiosflags(std::ios::left) << msg << std::resetiosflags(std::ios::left)
        << std::endl;
}

void printHook(const char* msg, void* p) {
    std::cout
        << std::setw(25) << std::setiosflags(std::ios::left) << msg << std::resetiosflags(std::ios::left)
        << std::setw(15) << std::setiosflags(std::ios::right) << p << std::resetiosflags(std::ios::right)
        << std::endl;
}

class MyT {
public:
    MyT() { printHook("constructor call", this); }
    MyT(MyT& t) { printHook("copy constructor call", this); }
    MyT(MyT&& t) { printHook("move constructor call", this); }

    ~MyT() { printHook("destructor call", this); v = 0; }

    MyT& operator=(MyT& t) { printHook("copy assigment call", this); return *this; }
    MyT& operator=(MyT&& t) { printHook("move assigment call", this); return *this; }

    int v = 1;
};

MyT fn() { return MyT(); }

int main() {
    printSep("a");
    MyT a;

    printSep("MyT&& v1 = std::move(a)");

    MyT&& v1 = std::move(a);
    std::cout << v1.v << " " << &v1 << std::endl;

    printSep("MyT&& v2 = MyT()");

    MyT&& v2 = MyT();
    std::cout << v2.v << " " << &v2 << std::endl;

    printSep("MyT&& v3 = std::move(MyT())");

    MyT&& v3 = std::move(MyT());
    std::cout << v3.v << " " << &v3 << std::endl;

    printSep("MyT&& v4 = fn()");

    MyT&& v4 = fn();
    std::cout << v4.v << " " << &v4 << std::endl;

    printSep("MyT&& v5 = std::move(fn())");

    MyT&& v5 = std::move(fn());
    std::cout << v5.v << " " << &v5 << std::endl;

    printSep("end");

    return 0;
}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 0: a                            OK.
constructor call          0x7ffe656eeae0
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 1: MyT&& v1 = std::move(a)      OK. Makes sense.
1 0x7ffe656eeae0
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 2: MyT&& v2 = MyT()             OK. Makes sense.
constructor call          0x7ffe656eeae8
1 0x7ffe656eeae8
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 3: MyT&& v3 = std::move(MyT())  NOT OK.
constructor call          0x7ffe656eeaec
destructor call           0x7ffe656eeaec
1 0x7ffe656eeaec
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 4: MyT&& v4 = fn()              NOT OK.
constructor call          0x7ffe656eeaf0
1 0x7ffe656eeaf0
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 5: MyT&& v5 = std::move(fn())   NOT OK.
constructor call          0x7ffe656eeaf4
destructor call           0x7ffe656eeaf4
1 0x7ffe656eeaf4
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 6: end
destructor call           0x7ffe656eeaf4
destructor call           0x7ffe656eeaf0
destructor call           0x7ffe656eeae8
destructor call           0x7ffe656eeae0

这些问题针对步骤3、4、5。

    • 3**

这是怎么回事?
为什么和第二步不一样?
在同一地址0x7ffe656eeaec下,我们调用了constructor - destructor - print chain,却没有得到segfault,这怎么可能呢?\

    • 4和5**

内存是从哪里分配的?
我们如何从fn()调用的非动态分配中获得MyT示例的2个不同地址?
它是保留的静态调用内存吗?或者它们是在堆栈上分配的?就像编译器看到那些是本地变量,并在程序内存区域中为这些东西保留。但我查看了反汇编,这是一个普通的函数调用。我不能在动态数据上检查它,因为我不能创建右值数组。
设置哪个优化标志并不重要,因为结果是一样的。下面是build命令:

g++ -std=c++17 -g -Wall -O3 -pedantic
    • 更新1:**简化了代码示例。
oyjwcjzk

oyjwcjzk1#

1.这是未定义的行为,你把一个临时对象作为参数传递给std::move()的参数,这个参数是std::move()的一个局部变量,这个函数返回一个对局部变量的引用,一个返回的对局部变量的引用不会延长对象的生命,这是未定义的行为。

  • 问题经过编辑,原题问的是第10例,现在是第3例 *
  1. &&延长了临时对象的生存时间。
    1.是同一个问题3.

相关问题