请 Wolf0403 指点指点

hyifeng 2004-04-01 12:04:47
Wolf0403,我真是佩服你什么都能学的那么好。

回家试了一下,IL显示string一开始就实例化为System.String,不象int需经过装箱。
还有,果真预构造了原代码中出现的字符串形成一个“字符串池”。

std::basic_string<>也可能因为会重新分配内存,不是线程安全的。

那么如果我要在C++使用一个线程安全的字符串可以使用什么?

“String 作为“不变体”,猜想是可以提高效率”,怎解?



还有另一个贴的:
class Itf {
public:
virtual ~Itf() = 0;
};
void Itf::~Itf(){}
现在手里没有编译器,试不了,
能不能说一下上面程序的工作原理?


能不能抽空指点迷津。

谢谢谢谢谢谢谢谢谢。
...全文
10 点赞 收藏 17
写回复
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
Wolf0403 2004-04-01
对于几个线程共享一个 string 的情况,我设想的方法就是设置一个全局访问点,譬如只能返回一个引用,等等。这实际上和 string 类本身的设计无关,而更多的是相关于整个多线程程序的设计了。
回复
北极猩猩 2004-04-01
还有一个问题是关于c_str方法的,我们知道这个方法的功能是将string对象的内部指针作为指向只读数据的指针返回,以便与同传统的C-style字符串处理函数协作。
结合上面operator=的情况,如果一个线程中使用c_str获得了指针,而另一个线程执行了operator=,那么也会产生非法内存访问。
回复
北极猩猩 2004-04-01
对于string得多线程访问还有一个问题是体现在operator=上面的。
我们知道,operator=在调用时首先要释放左值对象自身占用的内存然后再重新分配内存,并复制右值对象的内容到左值对象。
在左值对象被多个线程共享时,如果一个线程中执行了赋值操作,这好在释放了内存时,另一个对象对string进行访问,那么很可能产生内存的非法访问问题。
回复
C8402 2004-04-01
stl已经写成了,没有设计为多线程安全。

如果实在是要多线程共享basic_string对象,可以为该对象做一个互斥访问点。
需要getObject(),和release()。

不过一旦申请了对象的线程出了问题一直不release(),相关线程都会瘫痪。
回复
Wolf0403 2004-04-01
一开始的时候有点晕了,呵呵。
字符串和多线程的交集可能出现在两个地方:1、全局对象或者多线程共享一个对象;2、带有 cow 的情况,几个对象共享一个底层内存空间。以前的 sgi stl basic_string 是 cow 的(为了效率)。但是在多线程情况下可能不能正常工作,所以新的 string 不再使用 cow 技术。每个 basic_string 对象都有自己的数据拷贝,各个对象独立工作,所以不会产生冲突。
对于几个线程共享一个对象,只有通过加锁的方法解决,提供一个 unique 的访问点。Java 的 synchronize 关键字提供了这个功能。如果在每个成员函数中使用 synchronize(this) 就可以保证线程安全。
回复
BluntBlade 2004-04-01
“无法实例化”有失偏颇。
应该说“具有pure virtual member function”的类无法被实例化,但是基类中的该pure virtual member function却可以不给出定义,除非是pure virtual dtor。
楼主可以思考一下为什么pure virtual dtor一定要给出定义。呵呵。
回复
hyifeng 2004-04-01
看来我对 pure virtual 的理解一直都错了,
我以为是“不给出一个实现”,所以无法实例化。
现在的理解是“无法实例化”+“子类必须重写”,

不知道对不对。
回复
BluntBlade 2004-04-01
pure virtual 和 virtual还是有区别的,嗬嗬。
只是一般考虑不到而已。

废人啊,我还以为你真的撒手不管啦,苦了下面的新手啊,嘿嘿。
回复
cgsw12345 2004-04-01
先听课,后玩游戏!呵呵!
回复
Wolf0403 2004-04-01
pure virtual 和 virtual 在本质上没有太大的区别。。。

刀子,我不过是潜水多冒泡少而已。

哪个高手熟悉多线程代码编写事宜的,能不能说说字符串的问题?
回复
BluntBlade 2004-04-01
如果缺少了这一句
void Itf::~Itf(){}
那是一定会出错的,而且出错的肯定是子类的dtor。
嗬嗬。

废人你居然在线呐,少见呐。
回复
Wolf0403 2004-04-01
virtual ~Itf() = 0; 只是一个函数的声明,没有定义。所以我专门加了一行
void Itf::~Itf(){}
这就是这个函数的定义了。
回复
BluntBlade 2004-04-01
如果你的类继承自一个具有pure virtual member function的类,那么在子类中必须给出该pure virtual member function的实现(即函数定义体),否则就出错。
至于基类中是否实现出该pure virtual member function,看程序员自己的喜好和需要。
在《Effective C++》有相关的条款可以解读。
回复
hyifeng 2004-04-01
声明为pure virtual,然后又给出一个定义,这种用法我还是第一次见到。
回复
hyifeng 2004-04-01
其实昨晚我也想过使用 pure virtual dtor,我对C++的各种特性不是很熟,纯粹是乱试,
结果是语法不通过。像下面:
class Itf {
public:
virtual ~Itf() = 0;
};

是不是因为我缺少了这一步:
void Itf::~Itf(){}

对于第二步意图我还是不清楚。
回复
BluntBlade 2004-04-01
搬凳子听课。
回复
Wolf0403 2004-04-01
先说后面一个(偶稍微明白一点的)
我记得你好像是在模拟 interface。Java 中的 interface 是规定了一个接口,本身不能有实现。因为 Java 本身没有 virtual 关键字,所以 interface 的所有方法都可以理解为 virtual 的。而且因为 interface 不能有实例(譬如 Runable r = new Runable(); 错误:Runable 是 interface)。C++ 中能符合以上几个要求的基本只有带 pure virtual 函数的类了。因为你要求一个空的 interface,而 C++ 中即使是一个空类,也会有构造和析构函数。同时,构造函数在 C++ 中不能是虚拟的,所以我选择对析构函数使用虚拟。为了防止产生该类对象,所以使用 pure virtual dtor。

再说说前面一个。
std::basic_string 本质上还是一个容器。std::string 就是一个 basic_string<char> 产生的类型。所以,与 .net 和 Java 的不变体字符串类不同,basic_string 的多线程安全方式和容器的多线程安全方式应该类似。。。
我没有具体使用过 MFC,但是刚才问了一下,CString 也不是多线程安全的(某高手说:肯定不是啊~)。。。
要实现一个多线程安全的字符串类,有一个办法是在每个可能修改内存状况的地方加锁(譬如,内部的 _Resize 之类的方法上)。这样势必导致效率的大幅下降。

最后回复之前听说:
MFC 的 CString 提供了 LockBuffer 方法。这样可以将内存锁定给一个 CString 对象而其它的 CString 都不能使用任何成员函数,直到解锁为止。但是这是解决 COW 下的多线程问题,对于非 COW 而是直接共享一个对象的情况可能不适用。。。写一个 LockPtr 之类的东西包装供多线程环境使用如何?高手见笑了。
回复
发动态
发帖子
工具平台和程序库
创建于2007-09-28

2.4w+

社区成员

C/C++ 工具平台和程序库
申请成为版主
社区公告
暂无公告