没有复制构造函数问题的类?

时间:2012-03-29 13:02:41

标签: c++

我有一个没有复制构造函数或operator=重载的类。 代码非常大,但问题在于这个伪代码:

ClassA object1(x,y);
object1.add(z)
myVector.push_back(object1);

//Now when I retrieve from myVector and do add it
// apparently creates another object
myVector.at(index).add(z1);

就像我说的那样是伪代码。我希望对那里的专家有意义!

因此,ClassA看起来像这样(当然不包括所有数据成员)

Class ClassA {

private:
    int x;
    string y;
    ClassB b;
    vector<int> i;
public:
    int z;

}

由于ClassB b是此版本的新数据成员,现在是否需要复制构造函数? 再次感谢所有人的回复。

Class ClassB {
private:
vector<ClassC*> c;
Class D
}
Class ClassC {
private:
vector<ClassE*> e;
}
Class ClassD{
private:
vector<ClassF*> f;
}

然后ClassE和ClassF具有基本类型,如int和string。

6 个答案:

答案 0 :(得分:1)

使用时检索对象时未创建新对象 at(); at()返回对它的引用。新的对象正在 执行push_back()时创建。如果你没有 可访问的复制构造函数或赋值运算符,你不能把它 将对象转换为向量;官方来说,这是不确定的行为,但至少 如果你使用矢量(就像你在这里所做的那样),它实际上不会 编译。您很可能正在获得编译器生成的默认值。 没有看到实际的对象类型,我们就不可能说出来 他们是否合适;如果对象类型只包含基本类型 标准库中的类型和类型(除了iostream之外的东西) 和auto_ptr - 以及线程化的东西,如果你使用的是C ++ 11), 那么编译器生成的复制构造函数和赋值应该是 好。如果类包含指向内存的指针,则在 构造函数,它几乎肯定不是。

答案 1 :(得分:0)

push_back创建副本,因为它按值接收参数。如果您不想使用复制构造函数,请将向量定义为指向对象的指针向量,然后按下指针。

答案 2 :(得分:0)

检索时必须创建临时值,因为存储的值是副本。

答案 3 :(得分:0)

我怀疑它是使用复制构造函数,而只是简单的旧结构副本。

myVector.at(index)
在这种情况下,

返回ClassA,而不是ClassA &

您应该可以通过以下方式解决此问题:

ClassA & refObj = myVector.at(index);
refObj.add(z1);

我整理了一个在Visual Studio上有惊人结果的小测试。

class Boo {
public:
    void add() { a++; }
    int a;
};


vector<Boo> v;
Boo b;
b.a = 1;
for (int i=0; i<5; i++) {
    v.push_back(b);
}
v[0].add();
v.at(1).add();
Boo & refB = v[2]; refB.add();
refB = v.at(3); refB.add();
Boo & refB2 = v.at(4); refB2.add();
printf("%d %d %d %d %d\n", v[0].a, v[1].a, v[2].a, v[3].a, v[4].a);

结果:

2 2 2 1 2

所以编译器会对待:

Boo & refB = v[2]; refB.add();
refB = v.at(3); refB.add();

与以下不同:

Boo & refB2 = v.at(4); refB2.add();

但我没有得到原始问题(即v.at(n).add()不是复制,而是通过引用传递)。您确定以下行正在复制吗?

myVector.at(index).add(z1)

这可能是特定于编译器的吗?你使用什么编译器/操作系统?

答案 4 :(得分:0)

  

我有一个没有复制构造函数或operator =重载的类。

这并不重要。除非您明确禁用它们(声明为私有并且未在C ++ 03中实现,在C ++ 11中定义为delete),编译器将为您生成一个。

现在,如果您禁用复制对象,您将意识到您不能再将它们直接存储在矢量中,因为矢量将在内部复制参数。另一方面,您可以在容器中存储(智能)指针,但这可能会使您想要解决的问题复杂化。

答案 5 :(得分:0)

  

我有一个没有复制构造函数或operator =重载的类。

在这种情况下,编译器会为您提供这些。引用C ++ 2003标准,第12.8节:

  

如果类定义没有显式声明复制构造函数,则会声明隐式。 ...类X的隐式声明的复制构造函数将具有该表单   X::X(const X&) [或] X::X(X&)。 ...类X的隐式定义的复制构造函数执行其子对象的成员复制。

  

如果类定义未显式声明复制赋值运算符,则会声明隐式。 ...类X的隐式声明的复制赋值运算符的格式为X& X::operator=(const X&) [或] X& X::operator=(X&)。 ...类X的隐式定义的复制赋值运算符执行其子对象的成员分配。