gpt4 book ai didi

c++ - C++11强制无条件移动吗?

转载 作者:可可西里 更新时间:2023-11-01 18:18:21 26 4
gpt4 key购买 nike

我使用命令 g++ -std=c++11 t.cpp 编译以下代码:

#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

从日志来看,我的印象是:

  1. GCC 忽略复制构造函数 s(const s &other) .
  2. GCC 自动创建一个 move class s 的构造函数然后 std::vector.push_back()称之为move构造函数。

    This article

    因此,如果类 C 的定义没有明确声明一个移动赋值运算符,一个将被隐式仅当满足以下所有条件时才宣告违约满足:

    我的问题是 class s显然有一个用户声明的析构函数 ~s() , 意思是 class s不满足第四个条件,因此 GCC 不应强制执行 movestd::vector.push_back() . GCC 是如何表现的?

  3. 析构函数 ~s()被调用两次:第一次是在临时 s() 之后已作为参数传递给 ss.push_back(s()); 并移动,在 std::vector<s> 的析构函数之后第二个被称为。

  4. 因为这段代码不符合rule of three , 当 std::vector<s> 的析构函数时注定会崩溃叫做。 p指向的内容在对象中 s已被第一个 ~s() 删除.因此,std::vector<s>析构函数调用 ~s()必须崩溃并出现类似 double free or corruption 的错误.

然而,令我惊讶的是,这个程序以某种方式正常运行和终止。

问题一:为什么程序没有崩溃?我只是幸运吗?

问题2:根据gdb日志,这是否意味着为之前的 C++11 session 设计的代码 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.调用已有的拷贝构造函数。

感谢大家的大力帮助!

最佳答案

GCC ignores copy constructor s(const s &other).

作为复制省略优化,它很可能会这样做。

GCC automatically creates a move constructor for class s and then std::vector.push_back() calls that move constructor.

没有。不生成移动构造函数。

My question here is that class s apparently has a user-declared destructor ~s(), meaning class s does not meet the forth condition

正确。该类也不满足第一个条件(用户声明的复制构造函数)。

How does GCC behaves so?

GCC 似乎表现得很好。不涉及移动构造或分配。

Destructor ~s() is called two times

在您显示的 gdb 日志中,我只看到一个 s::~s 实例被调用。

question 1: Why the program does not crash? Am I simply lucky?

我会认为你不走运。看来push_back没有使用复制赋值运算符,所以double free的条件没有出现。

question 2: According to gdb log, does it mean that codes designed for prior C++11 meeting rule of three but not meeting rule of five, like this example...

此示例不符合三规则,因此这似乎不是您所要求的示例。

are very likely to crash when they are compiled to C++11 executables?

没有。只要代码遵循三的规则,复制对象就是安全的。只有在使对象可移动(避免复制)时才需要遵循五规则。

关于c++ - C++11强制无条件移动吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40907276/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com