我刚刚创建了一个带有整数变量和指针变量的类。创建对象后,我将其传递给函数。即使在返回函数之后,程序也没有抛出异常
#include"iostream"
using namespace std;
class A
{
public :
int i;
char *c;
void show();
};
void func(A obj);
int main()
{
A a;
a.i = 10;
a.c = "string";
cout << " Before Fun " << endl;
a.show();
cout << " Going To Call func " << endl;
func(a);
cout << " After func " << endl;
a.show();
return 0;
}
void A::show()
{
cout << " The valuses in Object are " << i << '\t' << c << endl;
}
void func(A aa)
{
cout << " The valuses in Object are " << aa.i << '\t' << aa.c << endl;
}
在Func中,我传递对象a(从main),它将被复制到aa(func的堆栈)中。所以从func返回后如果我调用show(指针c将为null),它会给我异常 但它没有发生。请帮我证明复制构造函数的要求
答案 0 :(得分:7)
隐藏复制构造函数。这会在隐式调用的任何地方引起编译错误。
class A
{
public :
int i;
char *c;
private:
A(const A& _other);
};
答案 1 :(得分:1)
如果没有为对象声明复制构造函数,则隐式定义一个复制构造函数。此复制构造函数复制对象的每个元素。
在您的示例中,对func(a)
的调用将调用此复制构造函数,因此aa
将是a
的副本(aa.i
将为10
}和aa.c
将指向"string"
)的第一个元素。
答案 2 :(得分:1)
如果您使用的是C ++ 11,则可以执行以下操作以删除复制构造函数
class A
{
public :
int i;
char *c;
void operator=(const A& _other) = delete;
A(const A& _other) = delete;
};
甚至更好:
class A : public NonCopyable // perhaps std:: or if you prefer boost, boost::
{
public :
int i;
char *c;
};
http://en.wikipedia.org/wiki/C++11#Explicitly_defaulted_and_deleted_special_member_functions
答案 3 :(得分:0)
如果您没有明确定义隐式复制构造函数,则它确实存在。它在您的func()
函数中调用。 A
对象被复制并为其成员i
分配值。
结果将是:您在调用show()
之前获得i
之前的func
值。这并不奇怪,因为您没有对A
内的A成员进行任何分配。
编译器的隐式复制构造函数提供成员复制。这是大多数情况下您可能需要的。
默认构造函数何时不够?你有像成员的指针,需要它的深层副本。您不希望复制指针(复制构造函数将执行的操作),而是将对象指向复制。但为什么你需要深层复制?您不希望复制指针(由该类的任何实例拥有),并最终在同一指针上调用两次析构函数。从该指针的第二次调用delete
开始,堆腐败随之而来。您可能还需要为shared_pointers明确复制构造函数。
请注意,出于性能原因,最好通过const引用传递对象而不是按值传递。
答案 4 :(得分:0)
在您的情况下,编译器提供的复制构造函数存在。
修改代码并将复制构造函数编写为:
//Default and copy constructor
A()
{
i = 0;
c = NULL;
}
A(const A& _other)
{
cout<<"In copy cons"<<endl;
}
当你在 func 被调用时修改上面的代码时,你自己的拷贝构造函数被调用,在这种情况下你会得到垃圾值(无法预测)
如果您将复制构造函数代码修改为
A(const A& _other)
{
cout<<"In copy cons"<<endl;
i = _other.i;
c = new char [(strlen(_other.c) +1)];
strcpy(c,_other.c);
}
现在您可以看到两个输出的差异以及复制构造函数的使用方式和使用位置。
答案 5 :(得分:0)
创建类时,隐式存在null构造函数和复制构造函数。 所以这就是它不会抛出异常的原因。 但是,如果您定义了任何构造函数,则需要定义其他构造函数,否则其他构造函数将被覆盖。 例如,您只定义一个null构造函数。然后它会抛出异常。因为将重写隐式定义的复制构造函数。 这是证明需要复制构造函数的一种方法。