AnyClass [英] AnyClass

查看:69
本文介绍了AnyClass的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了两个文件:


anyclass.cpp

anyclass.hpp

其中是定义类AnyClass。它用于测试

的目的和玩耍,玩得开心。


类的作用是(可选)每当一个对象打印文本它是

创建,销毁,分配给。


构造函数的工作原理如下:


AnyClass blah (blah);

你提供一个名字。该名称将被复制到其内部的

存储空间中。所有打印的文本都将按名称引用对象。如果你

,请执行以下操作:


AnyClass poo = blah;


然后对象poo将有一个名称复制blah。

这里是它的公共成员:


object_counter:类型为的静态只读变量 ;无符号"它持有

AnyClass对象的数量。目前存在。


GetName():返回一个指向字符串的指针,该字符串包含

对象的名称。


to_play_with:只是一个类型为unsigned的非const成员变量。玩



这是一个示例用法:

#include" anyclass.hpp"


int main()

{

AnyClass const& blah = AnyClass(" no-name");


std :: cout<< \ nHaHa \ n;

}

此程序将输出以下内容:


AnyClass构造函数:没有名字


HaHa

AnyClass析构函数:无名

这表明上面的临时版有效直到

功能的结束。


如果您不想要课程打印出来,请执行以下操作:


#define ANYCLASS_NO_OUTPUT

#include" anyclass.hpp"
但不幸的是你还需要编辑.cpp ;文件也要实现

这个。

这是它。 。 。


//anyclass.hpp

#ifndef INCLUDE_ANYCLASS_HPP

#define INCLUDE_ANYCLASS_HPP


#ifndef ANYCLASS_NO_OUTPUT

#include< iostream>

#endif


#include< cstddef> ;

#include< cstring>


class AnyClass

{

public:


static unsigned const& object_counter;


unsigned to_play_with;

const char * GetName()const

{

返回姓名;

}

私人:


静态无符号object_counter_prv;

char * name;


public:


AnyClass(const char * const in_name,unsigned const in_to_play_with = 0)

:to_play_with(in_to_play_with)

{


std :: size_t length = std :: strlen(in_name );


name = new char [length + = 1];


memcpy(name,in_name,length);


++ object_counter_prv;


#ifndef ANYCLASS_NO_OUTPUT

std :: cout<< " AnyClass构造函数: <<姓名<<

''\ n'';

#endif


}

AnyClass(AnyClass const& original):to_play_with

(original.to_play_with)

{

std :: size_t length = std: :strlen(original.name);


name = new char [length + = 9]; // 9 = 8 + 1(1为空

字符)


memcpy(name," Copy of",8); // 。 .waste of null

character


memcpy(& name [8],original.name,length - = 9); //取回9

后退


名称[长度+ = 8] =''\ 0'';

++ object_counter_prv;


#ifndef ANYCLASS_NO_OUTPUT

std :: cout<< AnyClass Copy Constructor for: <<名称<< ''\ n'';

#endif

}


AnyClass& operator =(AnyClass const& other)

{

//注意:没有任何名称更改


to_play_with = other.to_play_with;


#ifndef ANYCLASS_NO_OUTPUT

std :: cout<< " AnyClass Assignment Operator: <<名称<<

=" << other.name<< ''\ n'';

#endif


返回* this;

}

~AnyClass()

{

#ifndef ANYCLASS_NO_OUTPUT

std :: cout<< " AnyClass析构函数: << name<<

''\ n'';

#endif


delete [] name;

--object_counter_prv;

}

};

#endif


//anyclass.cpp


#include" anyclass.hpp"


unsigned AnyClass :: object_counter_prv = 0;

unsigned const& AnyClass :: object_counter = AnyClass :: object_counter_prv;


欢迎任何评论,问题和建议。

-JKop

I''ve written two files:

anyclass.cpp
anyclass.hpp
Within is the definition of the class "AnyClass". It''s used for testing
purposes and for playing around, having some fun.

What the class does is (optionally) print text whenever an object of it is
created, destroyed, assigned to.

The constructor works as so:

AnyClass blah("blah");
You supply it with a name. This name will be copied into its internal
storage. All text which is printed will refer to the object by name. If you
do the following:

AnyClass poo = blah;

Then the object "poo" will have the name "Copy of blah".
Here''s its public members:

object_counter : a static read-only variable of type "unsigned" which holds
the amount of objects of "AnyClass" currently in existence.

GetName() : returns a pointer to the string which contains the name of the
object.

to_play_with : just a non-const member variable of type "unsigned" to play
around with.
Here''s an example usage:
#include "anyclass.hpp"

int main()
{
AnyClass const &blah = AnyClass("no-name");

std::cout << "\nHaHa\n";
}
This program will output the following:

AnyClass Constructor for: no-name

HaHa
AnyClass Destructor for: no-name
Which shows that the temporary in the above is valid until the end of the
function.

If you don''t want the class to print out at all, then do the following:

#define ANYCLASS_NO_OUTPUT
#include "anyclass.hpp"
but unfortunately you''ll also have to edit the ".cpp" file also to achieve
this.
Here it is. . .

//anyclass.hpp

#ifndef INCLUDE_ANYCLASS_HPP
#define INCLUDE_ANYCLASS_HPP

#ifndef ANYCLASS_NO_OUTPUT
#include <iostream>
#endif

#include <cstddef>
#include <cstring>

class AnyClass
{
public:

static unsigned const &object_counter;

unsigned to_play_with;
const char* GetName() const
{
return name;
}
private:

static unsigned object_counter_prv;
char* name;

public:

AnyClass(const char* const in_name, unsigned const in_to_play_with = 0)
: to_play_with(in_to_play_with)
{

std::size_t length = std::strlen( in_name );

name = new char[length += 1];

memcpy(name, in_name, length);

++object_counter_prv;

#ifndef ANYCLASS_NO_OUTPUT
std::cout << " AnyClass Constructor for: " << name <<
''\n'';
#endif

}
AnyClass(AnyClass const &original) : to_play_with
(original.to_play_with)
{
std::size_t length = std::strlen( original.name );

name = new char[length += 9]; //9 = 8 + 1 (1 for the null
character)

memcpy( name, "Copy of " , 8 ); // . . .waste of a null
character

memcpy( &name[8], original.name, length -= 9 ); //Take the 9
back off

name[length += 8] = ''\0'';

++object_counter_prv;

#ifndef ANYCLASS_NO_OUTPUT
std::cout << "AnyClass Copy Constructor for: " << name << ''\n'';
#endif
}

AnyClass& operator=(AnyClass const &other)
{
//NB: There is no name change whatsoever

to_play_with = other.to_play_with;

#ifndef ANYCLASS_NO_OUTPUT
std::cout << " AnyClass Assignment Operator: " << name << "
= " << other.name << ''\n'';
#endif

return *this;
}

~AnyClass()
{
#ifndef ANYCLASS_NO_OUTPUT
std::cout << " AnyClass Destructor for: " << name <<
''\n'';
#endif

delete [] name;
--object_counter_prv;
}
};
#endif

//anyclass.cpp

#include "anyclass.hpp"

unsigned AnyClass::object_counter_prv = 0;
unsigned const &AnyClass::object_counter = AnyClass::object_counter_prv;


Any comments, questions, suggestions welcomed.
-JKop

推荐答案

2004年10月12日星期二13:34:44 GMT in comp.lang.c ++,JKop< NU ** @ NULL .NULL>

写道,
On Tue, 12 Oct 2004 13:34:44 GMT in comp.lang.c++, JKop <NU**@NULL.NULL>
wrote,
std :: size_t length = std :: strlen(original.name);

name = new char [长度+ = 9]; // 9 = 8 + 1(1为空
字符)

memcpy(name," Copy of",8); // 。 .waste of null


memcpy(& name [8],original.name,length - = 9); //取回9
返回
std::size_t length = std::strlen( original.name );

name = new char[length += 9]; //9 = 8 + 1 (1 for the null
character)

memcpy( name, "Copy of " , 8 ); // . . .waste of a null
character

memcpy( &name[8], original.name, length -= 9 ); //Take the 9
back off




在我看来,你应该使用std :: string并省略所有容易出错的内容

char * hacking。



In my opinion, you should use std::string and omit all that error-prone
char* hacking.


David Harmon发布:
David Harmon posted:
2004年10月12日星期二13:格林威治标准时间34:44 comp.lang.c ++,JKop
< NU ** @ NULL.NULL>写道,
On Tue, 12 Oct 2004 13:34:44 GMT in comp.lang.c++, JKop
<NU**@NULL.NULL> wrote,
std :: size_t length = std :: strlen(original.name);

name = new char [length + = 9]; // 9 = 8 + 1(
空字符为1)

memcpy(name," Copy of",8); // 。 .waste of null


memcpy(& name [8],original.name,length - = 9); //拿回
9关闭
std::size_t length = std::strlen( original.name );

name = new char[length += 9]; //9 = 8 + 1 (1 for the
null character)

memcpy( name, "Copy of " , 8 ); // . . .waste of a null
character

memcpy( &name[8], original.name, length -= 9 ); //Take
the 9 back off



在我看来,你应该使用std :: string并省略所有那些容易出错的问题。
char * hacking。



In my opinion, you should use std::string and omit all that error-prone
char* hacking.




我非常不同意。


上面没有任何错误,也没有任何黑客攻击。

这只是很好的''C ++。


在我看来,使用std :: string是一种耻辱。以及

之类的简单用法如上所述。没有人再相信效率了吗?


我会承认需要一些思考才能确保你把

放在正确的数组索引中,例如。 & name [8],但我真的很喜欢这个,而且我的b $ b最终得到了更高效的代码。


我会的但是说std :: string有很多用途。我用的时候是

我正在做*极限*字符串操作,特别是在我需要的时候我会不得不调整缓冲区的大小是我自己做的。在这种情况下,使用简单的std :: string可以优先使用
。成员而不是花一个小时搞乱字符。

-JKop



I strongly disagree.

There is nothing error-prone about the above, nor is there any "hacking".
It''s just good ol'' C++.

In my own opinion, it''s a disgrace to use "std::string" and the like for
simple uses like the above. Does no-one believe in efficiency anymore?

I will although admit that it takes a bit of thinking to make sure you put
in the right array indexes, eg. "&name[8]", but I actually enjoy that and I
end up with much more efficient code.

I''ll say that there are however great uses for "std::string". I use in when
I''m doing *extreme* string manipulation, especially where I would have to
resize the buffer were I to do it myself. In the cases, it''s preferrable to
use simple "std::string" members than to spend an hour messing with chars.
-JKop


JKop< NU ** @ NULL.NULL>在消息新闻中写道:< Df ******************* @ news.indigo.ie> ...
JKop <NU**@NULL.NULL> wrote in message news:<Df*******************@news.indigo.ie>...
David Harmon发布:


[...]
David Harmon posted:
[ ... ]
在我看来,你应该使用std :: string并省略所有这很容易出错
char * hacking。
In my opinion, you should use std::string and omit all that error-prone
char* hacking.



我非常不同意。

上面没有任何容易出错的信息,也没有任何错误hacking。
它只是很好的''C ++。

在我看来,使用std :: string是一种耻辱。等等,如上所述的简单用途。没有人再相信效率吗?



I strongly disagree.

There is nothing error-prone about the above, nor is there any "hacking".
It''s just good ol'' C++.

In my own opinion, it''s a disgrace to use "std::string" and the like for
simple uses like the above. Does no-one believe in efficiency anymore?




我们中的很多人都做了 - 我们意识到(例如)做了
$ b $使用C字符串函数,使用std :: string的作业通常比使用
更有效。


例如,您的代码包含对strlen的调用,这是一个

O(N)函数,因为它必须搜索整个字符串才能找到

结尾。相比之下,std :: string对象通常将

当前长度存储为成员,这意味着std :: string :: length()是一个简单的O(
) 1)功能。


因此,你的代码的速度(严重)取决于

original.name的长度。使用std :: string的实现可以删除

这个依赖关系,并且在其他方​​面保留基本相同(或更好)的效率

。不可避免地会有一段

original.name超出std :: string比你的

代码更有效 - 并且这个长度可能很容易为0。 />
我会承认需要一些思考才能确保你把
放在正确的数组索引中,例如。 & name [8],但我真的很喜欢,我最终会得到更高效的代码。



Quite a few of us do -- and we realize (for example) that doing the
job with std::string will often be substantially MORE efficient than
using C string functions.

Just for example, your code contains a call to strlen, which is an
O(N) function since it has to search through the entire string to find
the end. By contrast, an std::string object normally stores the
current length as a member, meaning that std::string::length() is a
trivial O(1) function.

As such, your code''s speed depends (heavily) on the length of
original.name. An implementation using std::string instead can remove
this depency, and retain essentially the same (or better) efficiency
in other areas as well. There will inevitably be a length of
original.name beyond which std::string is more efficient than your
code -- and that length may easily be 0.
I will although admit that it takes a bit of thinking to make sure you put
in the right array indexes, eg. "&name[8]", but I actually enjoy that and I
end up with much more efficient code.




这个名称一种代码是脆弱的。如果你坚持写这样的东西,那么最低限度的体面就是代码。

喜欢:


静态字符cpy [] ="复制的';;

静态size_t len = sizeof(cpy);


memcpy(name,cpy,len-1) ;

memcpy(名称+ len-1,original.name,length- = len);


这样,你就没有了 ;魔"代码中的数字为8,而不是使用其推导明显的值的
。更好的是,如果(对于

示例),有人决定将代码翻译成他们选择的除英语之外的其他语言,其中副本是副本。几乎可以肯定

是一个不同的大小,大小会随着字符串长度的变化而自动改变。


IMO,所有这一切基本上都没有意义:给定了标准库的合理实施,我希望

std :: string能够在同一个通用的球场速度为

手动执行此操作。为了测试这个理论,我使用std :: string创建了一个类的修改版本




//anyclass.hpp


#ifndef INCLUDE_ANYCLASS_HPP

#define INCLUDE_ANYCLASS_HPP


#ifndef ANYCLASS_NO_OUTPUT

#include< iostream>

#endif


#include< string>


class AnyClass

{

public:

static unsigned const& object_counter;


unsigned to_play_with;


std :: string const& GetName()const

{

返回名称;

}

私人:


static unsigned object_counter_prv;

std :: string name;


public:


AnyClass(s​​td :: string const& in_name,unsigned in_to_play_with =

0)

:to_play_with(in_to_play_with),name(in_name)

{

++ object_counter_prv;


#ifndef ANYCLASS_NO_OUTPUT

std :: cout<< " AnyClass构造函数: <<姓名<<

''\ n'';

#endif


}

AnyClass(AnyClass const& original):

to_play_with(original.to_play_with)

{

name = std :: string(" ;复制)+ original.name;

++ object_counter_prv;


#ifndef ANYCLASS_NO_OUTPUT

std :: cout << AnyClass Copy Constructor for: <<姓名<<

''\ n'';

#endif

}


AnyClass& operator =(AnyClass const& other)

{

//注意:没有任何名称更改


to_play_with = other.to_play_with;


#ifndef ANYCLASS_NO_OUTPUT

std :: cout<< " AnyClass Assignment Operator: <<

name<< " = << other.name<< ''\ n'';

#endif


返回* this;

}

~AnyClass()

{

#ifndef ANYCLASS_NO_OUTPUT

std :: cout<< " AnyClass析构函数: << name<<

''\ n'';

#endif

--object_counter_prv;

}

};


#endif


然后我掀起了一个快速测试工具:


#define ANYCLASS_NO_OUTPUT

#include< time.h>


#ifdef USESTRING

#include" anyclass.hpp"

#else

#include" anyclass1.hpp"

#endif


#include< iostream>

int main(){


const int num = 5000;


AnyClass * x [num];


clock_t start = clock();

x [0] = new AnyClass(" X");

for(int i = 1; i< num; i ++)

x [i] = new AnyClass(* x [i-1 ]);

clock_t整体=时钟() - 开始;


#ifdef USESTRING

std :: cout<< ; 长度: << x [num-1] - > GetName()。length();

#else

std :: cout<< 长度: << strlen(x [num-1] - > GetName());

#endif


std :: cout<< " \ nTime:" <<总体/(双)CLOCKS_PER_SEC<<

" seconds \ n" ;;

返回0;

}


我使用VC ++ 7.1编译代码:


cl / O2b2 / G7ry any.cpp anyclass.cpp

和:


cl / DUSESTRING / O2b2 / G7ry any.cpp anyclass.cpp


并运行两个版本。在我的特定机器上,两个版本声称

在.312秒内运行。有可能(实际上可能),如果你经常运行它们,你至少偶尔会看到一个

的速度差异(在一个时钟刻度的顺序,我会

猜测)。通过大量的运行和仔细的统计分析,你甚至可能会发现它们之间存在统计上显着的差异 -

但是没有更多的测试,它很难甚至猜猜哪一个可能会赢得
- std :: string可能会更快,因为
更慢。在任何情况下,我认为这或多或少都是无关紧要的:那里有

没有真正的空间可以解释使用std :: string的代码很多

更简单,使用原始char *的代码显然不是更快,

这是证明自己存在的必要条件。


我还会注意到使用原始指针会使异常安全性提高

更难以提供。


-

后来,

杰瑞。


宇宙是自己想象的虚构。



The name for that kind of code is "fragile." If you insist on writing
something like this, a bare minimum of decency would be code something
like:

static char cpy[] = "Copy of ";
static size_t len = sizeof(cpy);

memcpy(name, cpy, len-1);
memcpy(name+len-1, original.name, length-=len);

This way, you don''t have a "magic" number like 8 in the code, instead
using a value whose derivation is obvious. Better still, if (for
example) somebody decided to translate the code to their choice of
languages other than English, where "copy of" would almost certainly
be a different size, the size would automatically change with the
change in string length.

IMO, all of this remains essentially pointless: given a halfway
reasonable implementation of the standard library, I''d expect
std::string to be right in the same general ballpark for speed as
doing this manually. To test this theory, I created a modified version
of your class using std::string:

//anyclass.hpp

#ifndef INCLUDE_ANYCLASS_HPP
#define INCLUDE_ANYCLASS_HPP

#ifndef ANYCLASS_NO_OUTPUT
#include <iostream>
#endif

#include <string>

class AnyClass
{
public:
static unsigned const &object_counter;

unsigned to_play_with;

std::string const &GetName() const
{
return name;
}
private:

static unsigned object_counter_prv;
std::string name;

public:

AnyClass(std::string const &in_name, unsigned in_to_play_with =
0)
: to_play_with(in_to_play_with), name(in_name)
{
++object_counter_prv;

#ifndef ANYCLASS_NO_OUTPUT
std::cout << " AnyClass Constructor for: " << name <<
''\n'';
#endif

}
AnyClass(AnyClass const &original) :
to_play_with(original.to_play_with)
{
name = std::string("Copy of ") + original.name;
++object_counter_prv;

#ifndef ANYCLASS_NO_OUTPUT
std::cout << "AnyClass Copy Constructor for: " << name <<
''\n'';
#endif
}

AnyClass& operator=(AnyClass const &other)
{
//NB: There is no name change whatsoever

to_play_with = other.to_play_with;

#ifndef ANYCLASS_NO_OUTPUT
std::cout << " AnyClass Assignment Operator: " <<
name << " = " << other.name << ''\n'';
#endif

return *this;
}

~AnyClass()
{
#ifndef ANYCLASS_NO_OUTPUT
std::cout << " AnyClass Destructor for: " << name <<
''\n'';
#endif
--object_counter_prv;
}
};

#endif

and then I whipped together a quick test harness:

#define ANYCLASS_NO_OUTPUT

#include <time.h>

#ifdef USESTRING
#include "anyclass.hpp"
#else
#include "anyclass1.hpp"
#endif

#include <iostream>
int main() {

const int num = 5000;

AnyClass *x[num];

clock_t start = clock();
x[0] = new AnyClass("X");
for (int i=1; i<num; i++)
x[i] = new AnyClass(*x[i-1]);
clock_t overall = clock()-start;

#ifdef USESTRING
std::cout << "length: " << x[num-1]->GetName().length();
#else
std::cout << "length: " << strlen(x[num-1]->GetName());
#endif

std::cout << "\nTime: " << overall/(double)CLOCKS_PER_SEC <<
" seconds\n";
return 0;
}

I compiled the code with VC++ 7.1 using:

cl /O2b2 /G7ry any.cpp anyclass.cpp

and:

cl /DUSESTRING /O2b2 /G7ry any.cpp anyclass.cpp

and ran both versions. On my particular machine, both versions claimed
to run in .312 seconds. It''s possible (probable, in reality) that if
you ran them often enough that you''d at least ocassionally see a
difference in speed (on the order of a single clock tick worth, I''d
guess). With a lot of runs and careful statistical analysis, you might
even even find a statistically significant difference between them --
but without more testing, it''s hard to even guess which one would be
likely to win -- std::string might be about as likely to be faster as
slower. In any case, I think that''s more or less irrelevant: there''s
no real room for question that the code using std::string is a LOT
simpler, and the code using raw char *''s clearly is not a LOT faster,
which is what would be needed to justify its own existence.

I''d also note that using raw pointers makes exception safety
considerably more difficult to provide.

--
Later,
Jerry.

The universe is a figment of its own imagination.


这篇关于AnyClass的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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