我有一个没有复制构造函数或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。
答案 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的隐式定义的复制赋值运算符执行其子对象的成员分配。