复制构造函数和其他问题 [英] Copy Constructor and other questions

查看:60
本文介绍了复制构造函数和其他问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有几个问题。


1.复制构造函数。


A级{

私人:

int a1;

双d1;

char * ptr;


public:

const A * operator =(const A * b)

{

memcpy(this,b,sizeof(A));

ptr = new char [100];

};


};


int main()

{

A * b =新b;

A * c = b;

.......

..........

};


C ++是否保证我的memcpy总是与Object完全重复

''b''无论类有多大。这是编写副本的一般方式

构造函数吗?

2.空引用。例如,我们有一个搜索列表的函数和

返回指向对象的指针(如果找到)或NULL如果找不到

对象。如果我想返回一个引用而不是一个

指针,而不抛出异常,我怎么能这样做?

3.这段代码来自FAQ lite。


class Point {

public:

static Point rectangle(float x,float y); //矩形坐标'

静态极点(浮点半径,浮点角); //极坐标

//这些静态方法是所谓的命名构造函数

...

private:

Point(float x,float y); //矩形坐标

float x_,y_;

};


内联Point :: Point(float x,float y )

:x_(x),y​​_(y){}


内联点Point :: rectangle(float x,float y)

{return Point(x,y); }


内联点Point ::极地(浮点半径,浮点角)

{返回点(半径* cos(角度),半径* sin(角度) )); }


int main()

{

点p1 = Point :: rectangle(5.7,1.2); //显然是长方形

点p2 = Point :: polar(5.7,1.2); //显然是极地

...

}


愚蠢的问题。现在谁拥有p1和p2以及如何删除它们?


感谢您的时间和帮助

--MSR

解决方案

" MSR" < MS ******** @ comcast.net>写了...

我有几个问题。

1.复制构造函数。

A类{
私人:


默认情况下,班级中的所有内容都是私密的。不需要用不必要的结构来混乱你的
代码。

int a1;
double d1;
char * ptr;

public:
const A * operator =(const A * b)
{memcpy(this,b,sizeof(A));
ptr = new char [100 ];
};
^

这个分号是多余的。

};

int main()
{
A * b =新b;
A * c = b;


如果您只是将它们声明为对象并且

并不忙于新或删除会更容易''至少一段时间。

............
.........
};

C ++是否保证我的memcpy始终完全复制Object
'b'',无论类有多大。


C ++保证在C库函数方面没有任何意义。那是'C'的b
工作来保证这些。由于C知道关于类的问题,因此使用带有非POD类型的memcpy的
是_undefined_。

这是编写复制构造函数的一般方法吗?


当然不是。首先,你写的是赋值运算符

而不是复制构造函数。其次,使用memcpy和类(因为我已经提到过
)是未定义的。第三,即使定义了它也是非常危险的。相信我,你不想用memcpy复制类

对象。只需对所有

数据使用复制构造语义。如果它是一个动态数组,通过分配然后使用

std :: copy复制它。


另外,你写的A类(a)不复制

所指的数组成员''ptr''(而只是分配它而不管它)

和(b)缺乏任何其他建筑。也许你不想写其他[无关]的东西,但是当使用动态内存管理时,

三个规则。必须遵循(或其他)。

2.空参考。


没有这样的东西。

例如我们有一个搜索列表的函数,如果找到它就会返回一个指针
如果找不到对象,则返回NULL。如果我想返回引用而不是指针,而不是抛出异常,我怎么能这样做呢?


你不能。

3.此代码来自FAQ lite。

class Point {
public:
static Point矩形(float x,float y); //矩形坐标'
静态极点(浮点半径,浮点角); //极坐标
//这些静态方法是所谓的命名构造函数
...
私有:
Point(float x,float y); //矩形坐标
浮动x_,y_;
};

内联Point :: Point(float x,float y)
:x_(x),y​​_ (y){}

内联点Point :: rectangle(float x,float y)
{return Point(x,y);内联点Point ::极地(浮点半径,浮点角)
{返回点(半径* cos(角度),半径* sin(角度)); }

int main()
{p / Point} p1 = Point :: rectangle(5.7,1.2); //显然是矩形的
点p2 = Point :: polar(5.7,1.2); //显然是极地
...
}

愚蠢的问题。现在谁拥有p1和p2以及如何删除它们?




它们是自动变量,将在

结束时处理掉''主要''功能体。没有人拥有他们并不需要明确删除
。只有''new''创建的对象需要

''删除'。


你读的什么书都没有说话关于复制构造

和自动变量?

V


MSR写道:

A级{
私人:
int a1;
双d1;
char * ptr;

公开:
const A * operator =(const A * b)
{memcpy(this,b,sizeof(A));
ptr = new char [100];
};

};

C ++保证我的memcpy总是与Object完全重复
''b''无论类多大。这是编写复制构造函数的一般方法吗?


是的,memcpy制作了指向内存的精确副本,但是......


NO,NO,NOOOOOOO这不是一般的写作方式

构造函数!!!此外,您编码的是赋值运算符。

嗯,有点。通常它们处理源引用的对象

对象,而不是指针。


考虑这些问题:


阿尔法;

alpha =& alpha; //暗示,想想内存泄漏


考虑将指针传递给从A派生的类??? IIRC''this''

指向* all *对象的存储空间,我相信大多数

实现的第一件事就是vtbl指针。所以你的b $ b盲目记忆会踩到A'的vtbl指针并指向

派生类'的vtbl。疯狂肯定是沿着这条道路走下去......我知道我知道,你的例子没有虚拟方法,但我在这里是一般的

。总的来说,memcpy在C ++中是一个坏主意。


A的一个更常见的复制构造函数如下所示:


A( const A& src):a1(src.a1),d1(src.d1),ptr(NULL)

{

if(src.ptr!= NULL)

{

ptr = new char [std :: strlen(src.ptr)+ 1];

std :: strcpy(ptr, src.ptr);

}

}


一个赋值运算符如下:

A& operator =(const A& src)

{

if(& src!= this)//检查自我分配

{

a1 = src.a1;

d1 = src.d1;

delete [] ptr;

if (src.ptr == NULL)

ptr = NULL;

else

{

ptr = new char [std :: strlen(src.ptr)+ 1];

std :: strcpy(ptr,src.ptr);

}

}

返回* this;

}


2.空参考。例如,我们有一个搜索列表的函数,如果找到对象,则返回指向对象的指针;如果找不到对象,则返回NULL。如果我想返回引用而不是
指针而不抛出异常,我该怎么做呢?


嗯,你可以返回一个NULL的引用,但是负担是在

代码上进行调用,记得检查并查看& ;

reffered-to对象是NULL。 (blech)


咬紧牙关,抛出异常。


不要返回引用。


创建一个默认值并将其插入,返回该引用。


有一个静态的空白或默认无值找到的对象,并返回一个

引用。

3.此代码来自FAQ lite。

class Point {
公开:
静态点矩形(float x,float y); //矩形坐标'
静态极点(浮点半径,浮点角); //极坐标
//这些静态方法是所谓的命名构造函数
...
私有:
Point(float x,float y); //矩形坐标
浮动x_,y_;
};

内联Point :: Point(float x,float y)
:x_(x),y​​_ (y){}

内联点Point :: rectangle(float x,float y)
{return Point(x,y);内联点Point ::极地(浮点半径,浮点角)
{返回点(半径* cos(角度),半径* sin(角度)); }

int main()
{p / Point} p1 = Point :: rectangle(5.7,1.2); //显然是矩形的
点p2 = Point :: polar(5.7,1.2); //显然是极地
...
}

愚蠢的问题。现在谁拥有p1和p2以及如何删除它们?




main()函数中的本地范围拥有这些对象。简短

回答 - 你不能删除它们。当函数

退出/返回时,编译器生成代码,以便
删除它们(在堆栈外,而不是堆!)。 (或抛出异常)


1。那不是复制构造函数。复制构造函数被命名为

与类相同,具有隐式(必须是隐式)返回类型

of void并获得类似的值

class_name const& ob

作为唯一参数。


你实现的是一个复制赋值运算符,它是什么

在构造之后作为左值参与作为左值时调用。为了说明这一点

class_name cl = c; //将调用复制构造函数

cl = c; //将调用复制赋值运算符

为了澄清一点,复制构造函数通常不涉及

memcpying另一个ob到this指针(

复制赋值运算符)。通常,任何

非指针成员都会使用正常的赋值

语句按值复制,并且任何指针成员都会被分配新的存储空间和

的内容将另一个对象的指针复制过来。


另外,您知道,测试代码,正如您已经实现的那样,将是
在将两个指针分配给

时执行标准分配另一个作为您实现的复制赋值运算符需要

作为其隐式第一个参数类型的对象A而不是A *。

2.如果找到一个指向对象的指针,那么为什么

你会将该函数声明为参考而不是指针?我不会理解你想用它完成什么。

3. p1和p2都是主函数所拥有的局部变量而且

会自动删除,因为它们是在堆栈上分配的,也就是说,

它们不需要通过任何特殊语法删除。


I have a couple of questions.

1. Copy Constructor.

class A {
private:
int a1;
double d1;
char *ptr;

public:
const A* operator=(const A* b)
{
memcpy(this, b, sizeof(A));
ptr = new char[100];
};

};

int main()
{
A *b = new b;
A *c=b;
.............
..........
};

Does C++ guarantee that my memcpy always make an exact duplicate of Object
''b'' no matter how big the class is. Is this a general way of writing copy
constructors?
2. Null Reference. For example we have a function that searches a list and
returns a pointer to an object if it is found or NULL if it can''t find the
object. How can I do this if I want to return a reference instead of a
pointer, without throwing exceptions?
3. This code is from FAQ lite.

class Point {
public:
static Point rectangular(float x, float y); // Rectangular coord''s
static Point polar(float radius, float angle); // Polar coordinates
// These static methods are the so-called "named constructors"
...
private:
Point(float x, float y); // Rectangular coordinates
float x_, y_;
};

inline Point::Point(float x, float y)
: x_(x), y_(y) { }

inline Point Point::rectangular(float x, float y)
{ return Point(x, y); }

inline Point Point::polar(float radius, float angle)
{ return Point(radius*cos(angle), radius*sin(angle)); }

int main()
{
Point p1 = Point::rectangular(5.7, 1.2); // Obviously rectangular
Point p2 = Point::polar(5.7, 1.2); // Obviously polar
...
}

Dumb question. Now who owns p1 and p2 and how can I delete them?

Thanks for your time and help
--MSR

解决方案

"MSR" <ms********@comcast.net> wrote...

I have a couple of questions.

1. Copy Constructor.

class A {
private:
Everything is private by default in a class. No need to clutter your
code with unnecessary constructs.
int a1;
double d1;
char *ptr;

public:
const A* operator=(const A* b)
{
memcpy(this, b, sizeof(A));
ptr = new char[100];
}; ^
This semicolon is superfluous.

};

int main()
{
A *b = new b;
A *c=b;
It would be so much easier if you just declared those as objects and
didn''t busy yourself with ''new'' or ''delete'' for at least a while.
............
.........
};

Does C++ guarantee that my memcpy always make an exact duplicate of Object
''b'' no matter how big the class is.
C++ guarantees NOTHING when it comes to C library functions. That''s C''s
job to guarantee those. And since C knows NOTHING about classes, the use
of memcpy with non-POD types is _undefined_.
Is this a general way of writing copy constructors?
Of course not. First of all what you wrote is an assignment operator
and not a copy constructor. Second, using memcpy with classes (as I
already mentioned) is undefined. Third, it is extremely dangerous even
if it were defined. Trust me, you don''t want go around copying class
objects using memcpy. Just use copy construction semantics for all your
data. If it''s a dynamic array, copy it by allocating and then by using
std::copy on it.

Also, class A as you wrote (a) does not copy the array pointed to by
the member ''ptr'' (and instead just allocates it and leaves it alone)
and (b) lacks any other construction. Perhaps you didn''t want to write
other [irrelevant] things, but when dynamic memory management is used,
the "rule of three" has to be followed (or else).
2. Null Reference.
No such thing exists.
For example we have a function that searches a list and returns a pointer
to an object if it is found or NULL if it can''t find the object. How can I
do this if I want to return a reference instead of a pointer, without
throwing exceptions?
You can''t.
3. This code is from FAQ lite.

class Point {
public:
static Point rectangular(float x, float y); // Rectangular coord''s
static Point polar(float radius, float angle); // Polar coordinates
// These static methods are the so-called "named constructors"
...
private:
Point(float x, float y); // Rectangular coordinates
float x_, y_;
};

inline Point::Point(float x, float y)
: x_(x), y_(y) { }

inline Point Point::rectangular(float x, float y)
{ return Point(x, y); }

inline Point Point::polar(float radius, float angle)
{ return Point(radius*cos(angle), radius*sin(angle)); }

int main()
{
Point p1 = Point::rectangular(5.7, 1.2); // Obviously rectangular
Point p2 = Point::polar(5.7, 1.2); // Obviously polar
...
}

Dumb question. Now who owns p1 and p2 and how can I delete them?



They are automatic variables and will be disposed of at the end of
the ''main'' function body. Nobody "owns" them and they don''t need to
be explicitly deleted. Only objects created by ''new'' need to be
''delete''d.

What book are you reading that doesn''t talk about copy construction
and automatic variables?

V


MSR wrote:

class A {
private:
int a1;
double d1;
char *ptr;

public:
const A* operator=(const A* b)
{
memcpy(this, b, sizeof(A));
ptr = new char[100];
};

};

Does C++ guarantee that my memcpy always make an exact duplicate of Object
''b'' no matter how big the class is. Is this a general way of writing copy
constructors?
Yes, memcpy makes an exact copy of the memory pointed to but...

NO, NO, NOOOOOOO This is not the general way of writing copy
constructors!!! Besides, what you coded is the assignment operator.
Well, sort of. Usually they deal with const references to the source
object, not pointers.

Consider these problems:

A alpha;
alpha = &alpha; // hint, think memory leak

Consider passing a pointer to a class derived from A??? IIRC ''this''
points to *all* the storage for the object, and I believe in most
implementations the first thing there is the vtbl pointer. So your
blind memcpy will step on the A''s vtbl pointer and point it at the
derived class''s vtbl. Madness surely lies down this path... I know I
know, your example doesn''t have virtual methods but I''m being general
here. And in general, memcpy is a bad idea in C++.

A more usual copy constructor for A would look something like:

A( const A& src ) : a1(src.a1), d1(src.d1), ptr(NULL)
{
if(src.ptr != NULL)
{
ptr = new char[ std::strlen(src.ptr) + 1 ];
std::strcpy(ptr,src.ptr);
}
}

And an assignment operator would look like:

A& operator=( const A& src )
{
if( &src != this ) // check for self-assignment
{
a1 = src.a1;
d1 = src.d1;
delete[] ptr;
if( src.ptr == NULL )
ptr = NULL;
else
{
ptr = new char[ std::strlen(src.ptr) + 1 ];
std::strcpy(ptr,src.ptr);
}
}
return *this;
}

2. Null Reference. For example we have a function that searches a list and
returns a pointer to an object if it is found or NULL if it can''t find the
object. How can I do this if I want to return a reference instead of a
pointer, without throwing exceptions?
Well, you can return a reference to NULL, but then the burden is on the
code making the call to remember to check and see if the & of the
reffered-to object is NULL. (blech)

Bite the bullet, throw exceptions.

Don''t return references.

Create a default and plug it in, return that reference.

Have a static "blank" or default no-value-found object and return a
reference to it.
3. This code is from FAQ lite.

class Point {
public:
static Point rectangular(float x, float y); // Rectangular coord''s
static Point polar(float radius, float angle); // Polar coordinates
// These static methods are the so-called "named constructors"
...
private:
Point(float x, float y); // Rectangular coordinates
float x_, y_;
};

inline Point::Point(float x, float y)
: x_(x), y_(y) { }

inline Point Point::rectangular(float x, float y)
{ return Point(x, y); }

inline Point Point::polar(float radius, float angle)
{ return Point(radius*cos(angle), radius*sin(angle)); }

int main()
{
Point p1 = Point::rectangular(5.7, 1.2); // Obviously rectangular
Point p2 = Point::polar(5.7, 1.2); // Obviously polar
...
}

Dumb question. Now who owns p1 and p2 and how can I delete them?



The local scope within the main() function owns the objects. Short
answer - you don''t delete them. The compiler generates code that
deletes them (off the stack, not the heap!) when the function
exits/returns. (or throws an exception)


1. That is not a copy constructor. A copy constructor is named the
same as the class, has an implicit (that must be implicit) return type
of void and gets a similar value to
class_name const &ob
as its only parameter.

What you have implemented is a copy-assignment operator which is what
is called when the class participates as an lvalue after it has been
constructed. To illustrate this
class_name cl = c; //Would call the copy constructor
cl = c; //Would call the copy-assignment operator
To clarify a bit more, copy constructors usually do not involve
memcpying the other ob to the this pointer (neither does the
copy-assignment operator for that matter). Normally, any
non-pointermembers are copied by value using normal assignment
statements and any pointer members are assigned new storage and the
contents of the other object''s pointer copied over.

Also, just so you know, the test code, as you''ve implemented it, will
do a standard assignment between the two pointers when assigning one to
the other as the copy-assignment operator that you did implement takes
as its implicit first parameter an object of type A and not type A*.
2. If you''re returning a pointer to an object if it is found, then why
would you declaring the function as reference and not pointer? I don''t
quite understand what you''re trying to accomplish with it.
3. p1 and p2 are both local variables owned by the main function and
are automatically deleted as they were allocated on the stack, that is,
they needn''t be deleted through any special syntax.


这篇关于复制构造函数和其他问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆