我编译使用命令g++ -std=c++11 t.cpp
下面的代码:C++ 11强制无条件移动吗?
#include <vector>
#include <cstring> //memcpy()
class s
{
char *p;
size_t size;
public:
s(){
size=10;
p=new char[size];
}
s(const s &other){
size=other.size;
p=new char[size];
memcpy(p,other.p,other.size);
}
~s(){ delete [] p; }
};
int main()
{
std::vector<s> ss;
ss.push_back(s());
}
这是gdb
日志:
Breakpoint 1, main() at t.cpp:23
23 ss.push_back(s());
s::s (this=0x7fffffffe370) at t.cpp:9
9 size=10;
10 p=new char[size];
11 }
std::vector<s, std::allocator<s> >::push_back(s&&) (this=0x7fffffffe350,
__x=<unknown type in /tmp/a.out, CU 0x0, DIE 0x20d0>)
at /usr/include/c++/4.9/bits/stl_vector.h:932
932 { emplace_back(std::move(__x)); }
std::move<s&> (__t=...) at /usr/include/c++/4.9/bits/move.h:102
102 { return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }
std::vector<s, std::allocator<s> >::emplace_back<s>(s&&) (this=0x7fffffffe350)
at /usr/include/c++/4.9/bits/vector.tcc:94
94 if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)
101 _M_emplace_back_aux(std::forward<_Args>(__args)...);
102 }
s::~s (this=0x7fffffffe370, __in_chrg=<optimized out>) at t.cpp:17
17 ~s(){ delete [] p; }
std::vector<s, std::allocator<s> >::~vector (this=0x7fffffffe350, __in_chrg=<optimized out>)
at /usr/include/c++/4.9/bits/stl_vector.h:425
从日志,我在下面的印象:
- GCC忽略副本构造函数
s(const s &other)
。 GCC会自动创建一个
move
构造函数class s
然后std::vector.push_back()
调用move
构造。因此,如果C类的定义不明确 声明的举动赋值运算符,一会隐含 声明为默认只有当所有的下列条件 满足:
我这里的问题是,
class s
显然有一个用户声明的析构函数~s()
,这意味着class s
不符合规定的条件,因此GCC不应std::vector.push_back()
执行move
。 GCC如何表现?析构函数
~s()
被称为两次:第一次临时立即之后s()
已作为参数传给了ss.push_back(s());
和移动,二是std::vector<s>
析构函数被调用后。- 由于此代码不符合rule of three,因此在调用
std::vector<s>
的析构函数时注定会崩溃。对象s
中p
指向的内容已被第一个~s()
删除。因此,std::vector<s>
析构函数调用~s()
必须崩溃,如double free or corruption
。
但是,让我吃惊的是,这个程序以某种方式运行并正常终止。
问题1:为什么程序不会崩溃?我真幸运吗?
问题2:根据gdb
日志,岂不是专为之前C++ 11次会议rule of three
但不符合rule of five,像这样的例子代码,很可能崩溃时被编译成C++ 11个可执行文件?
编辑:
这个问题是由于提高到我gdb
消息的误解这样的:
std::vector<s, std::allocator<s> >::push_back(s&&)
emplace_back(std::move(__x));
std::vector<s, std::allocator<s> >::emplace_back<s>(s&&)
导致我认为GCC创建一个移动构造函数。我只是做了很多这些专家告诉我的 - 在s(const s &other)
中设置了一个断点,并且注意到程序确实停在那里。这一发现使我的所有问题都无效。
由于每个专家建议在这里,事实是: 1. GCC不会产生任何移动构造函数。 2.调用现有的拷贝构造函数。
谢谢大家的帮助!
尝试在复制构造函数中放置断点。程序是否停在那个断点? –
这'push_back'内部调用了一个名为',以初始化新元素的std :: move'功能,但这种初始化使用拷贝构造函数(因为没有移动构造函数和拷贝构造函数是最好的搭配)。没有移动构造函数被生成或调用。 – cpplearner
@Someprogrammerdude我刚刚做到了。是的,程序停止在复制构造函数中。 –