【问题标题】:My copy constructor fails.. how to copy a pointer to an object我的复制构造函数失败..如何将指针复制到对象
【发布时间】:2013-10-12 06:04:19
【问题描述】:

我尝试为指向对象的指针向量编写一个复制构造函数,该对象在类 Shop 中初始化和声明。考虑的向量是:

std::vector <gCustomer*>   vCustomer;

在gShop的构造函数中也已经声明,在析构函数中通过循环删除。

现在我想在复制构造函数中获得指针向量的深层副本。但实际上没有任何内容被复制,如果我设法运行程序并访问 vCustomer,对其大小的检查仍然为零或使程序崩溃。 (请注意,如果我将复制构造函数排除在外,以便使用默认的复制构造函数,则程序运行正常)

gShop::gShop(const gShop & cShop)
    {
    for(int i = 0; i < (int)vCustomer.size(); ++i)
        {
        vCustomer[i]  = cShop.vCustomer[i];
        }
    }

谢谢

注意我也有指定的操作员

gShop gShop::operator=(const gShop & rhs)
   {
   if (this == &rhs) return *this;


    for(int i = 0; i < (int)vCustomer.size(); ++i)
        {
        delete vcustomer[i];
        vCustomer[i] = new gCustomer;
        vCustomer[i]= rhs.vCustomer[i];
        }
    }

【问题讨论】:

  • 什么版本的 C++ 和你使用什么编译器?最好使用 C++11,试试std::shared_ptrstd::vector&lt;std::shared_ptr&lt;gCustomer&gt;&gt;
  • 我不能使用 C++11.. 不知何故我不能用我的 opengl 东西编译它。我已经下载了boost,但我不知道如何安装它。我有 GCC 4.3.5。
  • 升级到较新版本的 GCC。 4.3 真的很旧 - 在 2010 年之前 - (并且不符合 C++11 标准)。当前的GCC 是 4.8.1(4.8.2 应该会在一两周内出现)
  • 这一切都很复杂。我在 5 年前开始了这个程序。它真的很大,而且有一些 opengl 的东西。如果我要升级,恐怕会需要大量的维护和重写。基本上当我尝试 GCC 4.8 时,我的编译器说不。当我升级我的编译器时,我的程序说不。
  • 我仍然认为使用 C++11(使用最新的 C++ 编译器,如 GCC 4.8 或 CLANG 3.3)确实值得付出努力。你的程序有多大(数百万行)?

标签: c++ copy-constructor


【解决方案1】:

您错误地实现了复制构造函数和赋值运算符,它们执行的是浅拷贝而不是深拷贝,并且它们不会调整目标向量的大小。这是一个深拷贝构造函数

gShop::gShop(const gShop & cShop)
{
for(int i = 0; i < (int)cShop.vCustomer.size(); ++i)
    {
    if (cShop.vCustomer[i])
        vCustomer.push_back(new gCustomer(*cShop.vCustomer[i]));
    else
        vCustomer.push_back(NULL);
    }
}

这是一个深拷贝赋值运算符

gShop& gShop::operator=(const gShop & rhs)
{
if (this == &rhs) return *this;
// clear any existing data
for(int i = 0; i < (int)vCustomer.size(); ++i)
    delete vcustomer[i];
vcustomer.clear();
// add the new data
for(int i = 0; i < (int)rhs.vCustomer.size(); ++i)
    {
    if (rhs.vCustomer[i])
        vCustomer.push_back(new gCustomer(*rhs.vCustomer[i]));
    else
        vCustomer.push_back(NULL);
    }
return *this;
}

基本上问题在于您正在复制指针而不是分配新内存。如果你想要一个深拷贝,你必须分配新的内存。

当然还有一个更大的问题,你为什么要使用指针向量。向量的一大优势是您不再需要显式管理内存,通过使用指针向量您失去了这种好处。我不知道你的程序,但在我看来std::vector&lt;gCustomer&gt; 会比std::vector&lt;gCustomer*&gt; 更好。使用std::vector&lt;gCustomer&gt;,您无需编写复制构造函数或赋值运算符,深复制将自动发生(假设gCustomer 进行深复制)。

【讨论】:

  • 由于前向声明的原因,我正在使用指针向量。我无法在该类中初始化对象,但可以初始化指向该对象的指针。
  • 我逐行复制。我遇到分段错误,调试器指出它在 vCustomer.push_back(new gCustomer(*cShop.vCustomer[i])) ?? 处崩溃
  • 好的,我知道这可能不是您现在最关心的问题,但我认为这不是正当理由。您应该重新组织您的代码,以便在 gShop 之前声明 gCustomer。但是你已经开始了这条路,所以我知道你可能会想继续。
  • 我有 12k 行代码和几十个类和派生类,这并不容易。试图找出所有不转发的那些类的组合排名,声明一切不是我打算做的。
  • @user2856452 这可能是因为您的 gCustomer 复制构造函数也存在错误。我猜你会因为指针使用不当而遇到所有这些问题。你正试图以艰难的方式做事。如果不确定,请发布 gCustomer 复制构造函数和赋值运算符。
【解决方案2】:

循环

gShop::gShop(const gShop & cShop)
    {
    for(int i = 0; i < (int)vCustomer.size(); ++i)
        {
        vCustomer[i]  = cShop.vCustomer[i];
        }
    }

使用了错误的限制。它应该从 0 到现有对象的长度:

i < (int)cShop.vCustomer.size()

【讨论】:

  • 当然,当您这样做时,您还需要确保 vCustomer 有足够的元素来允许对其进行索引。在循环前加上: vCustomer.resize(cShop.vCustomer.size());
【解决方案3】:

std::vector 本身具有复制构造函数来执行深层复制。 因此,编译器提供的复制构造函数将实际完成您想要的工作。 如果要自己实现,最好在gShop的构造函数的init列表中。

gShop::gShop(const gShop & cShop):vCustomer(cShop.vCustomer)
{
}

vCustomer 的大小在您的复制 ctor 中始终为零。

我对您的 operator=() 感到困惑。你想要什么? 我建议你阅读一些关于 C++ 入门的教科书。

【讨论】:

猜你喜欢
  • 2011-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-21
  • 2016-04-13
  • 1970-01-01
相关资源
最近更新 更多