- 已关闭**。此问题需要超过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:**简化了代码示例。
1条答案
按热度按时间oyjwcjzk1#
1.这是未定义的行为,你把一个临时对象作为参数传递给
std::move()
的参数,这个参数是std::move()
的一个局部变量,这个函数返回一个对局部变量的引用,一个返回的对局部变量的引用不会延长对象的生命,这是未定义的行为。&&
延长了临时对象的生存时间。1.是同一个问题3.