简体   繁体   English

如果类型仅使用 c++11 定义复制构造函数,则使用 std::vector 时 push_back 崩溃

[英]push_back crashed when using std::vector if the type only defined copy constructor with c++11

The code like this:像这样的代码:

#include <iostream>
#include <vector>

struct Foo
{
    int i;
    double d;
};

class Boo
{
public:
    Boo() : fptr(nullptr) 
    {
        std::cout << "Boo default construct..." << std::endl;
    }
    Boo(int i, double d):fptr(new Foo{i,d})
    {
    }

    Boo(const Boo &rhs) :fptr(new Foo{rhs.fptr->i,rhs.fptr->d})
    {
    }

    Foo *fptr;
};

int main(int argc, char const *argv[])
{
    std::vector<Boo> vec(1);
    Boo b(42, 10.24);
    vec.push_back(b);
    return 0;
}

Env: Ubuntu 16.4 LTS with gcc 5.4 g++ -std=c++11 test.cpp -o test -g环境:Ubuntu 16.4 LTS 与 gcc 5.4 g++ -std=c++11 test.cpp -o

./test 。/测试

If define move constructor,this will work good.如果定义移动构造函数,这将工作得很好。 I debuged it several hours but can not found what's wrong with it, maybe because some rules in c++ 11 that i did't know.我调试了几个小时,但找不到它有什么问题,可能是因为我不知道 c++ 11 中的一些规则。

Could somebody help me?有人可以帮我吗? Thanks!谢谢!

Your Boo copy constructor derefernces a pointer fptr that may be null.您的Boo复制构造函数取消引用可能是 null 的指针fptr

A std::vector::push_back may reallocate vector storage. std::vector::push_back可以重新分配向量存储。 Reallocating may use copy constructors.重新分配可以使用复制构造函数。

That is what is happening in your program.这就是您的程序中正在发生的事情。 You are copying a Boo that has a null pointer.您正在复制具有 null 指针的Boo

The problem is that in the copy constructor of Boo you're dereferencing a nullptr .问题在于,在Boo的复制构造函数中,您取消了对nullptr的引用。 This is because when you wrote:这是因为当你写:

std::vector<Boo> vec(1); //this creates a vector of size 1 using Boo's default constrcutor

This is what happens due to the above statement:这是由于上述声明而发生的情况:

  1. The above statement creates a vector named vec of size 1 using Boo 's default constructor .上面的语句使用Boo默认构造函数创建了一个大小为1的名为vec的向量。
  2. This means that there is already 1 Boo object inside vec .这意味着vec内部已经有1 Boo object 。 Moreover since this Boo object was created using the default constructor, its fptr is set to nullptr .此外,由于这个Boo object 是使用默认构造函数创建的,因此它的fptr设置为nullptr

Now, when you wrote:现在,当你写道:

vec.push_back(b);// this adds/push_back object b onto the vector vec so that now its size will be 2

Now, these are the important things that you have to remember here:现在,这些是您必须记住的重要事项:

  1. The vector has already 1 Boo object inside it which has its fptr as nullptr .该向量内部已经有1 Boo object ,其fptrnullptr
  2. Now you're adding one more element into the vector, reallocation may happen.现在您在向量中再添加一个元素,可能会发生重新分配 And if/when this reallocation happens, the copy constructor of Boo will be used.如果/当这种重新分配发生时,将使用Boo复制构造函数
  3. And when this copy constructor is used to copy the already present Boo object, it dereferences its fptr .当这个复制构造函数用于复制已经存在Boo object 时,它会取消引用它的fptr But since that fptr is nullptr and we know that dereferencing a nullptr is undefined behavior , so this may cause the program to segmentation fault as in your case.但是由于fptrnullptr并且我们知道取消引用nullptr未定义的行为,因此这可能会导致程序出现分段错误,就像您的情况一样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM