2010-06-03 115 views
5

有没有办法知道,如果一个对象是const对象或普通对象,例如考虑下面的类const对象和const构造

class String 
{ 
    String(const char* str); 
}; 

如果用户创建String const对象则没有复制传递的本地字符串的原因,并且因为他不会对它进行任何操作,他要做的唯一事情就是获取字符串大小,字符串搜索以及其他不会更改字符串的函数。

+5

有没有办法知道。实际上,'const'只有在对象被初始化(构造函数完成)后才会生效,并且一旦析构函数被输入就会停止。 – GManNickG 2010-06-03 21:07:15

回答

8

复制有一个非常好的理由 - 你不能知道const char *的生命周期与String对象的生命周期是一样的。不,没有办法知道你正在构造一个const对象。

2

不幸的是,C++没有提供一种方法来执行你正在尝试的操作。简单地传递一个const char *并不能保证被指向的内存的生命周期。考虑:

char * a = new char[10]; 
char const *b = a; 
String c (b); 
delete[] a; 
// c is now broken 
2

有没有办法让你知道。您可以编写一个与String紧密交互的类,并创建一个指向外部缓冲区的常量字符串(通过将相应的构造方法设置为private并使交互类为嵌套类或String的朋友)。

如果您担心的是对可能较小的常量字符串执行动态内存管理,则可以实现小字符串优化(也称为小对象/缓冲区优化)。它的工作方式是在字符串类中嵌入一个缓冲区,并将每个字符串复制到某个预定义大小的缓冲区中,并且每个字符串都大于动态分配的存储区(boost::function用于存储小型函数对象的相同技术) 。

class String { 
    union { 
    char *dynamicptr; 
    char buffer[16]; 
    }; 
    bool isDynamic; 
}; 

有用于存储即使在嵌入的字符串的长度到缓冲器本身(存储其长度为buffer[15]和类似trickeries)高明的技术。

0

你在找什么基本上是一个COW(拷贝写)字符串。这样的事情是完全可能的,但让他们工作是有点不平凡。在多线程的环境中,获得良好的性能可能会超越非常重要的难度范围。

1

你可以使用const_string来做你正在寻找的东西。但是,即使使用const字符串,也必须“告诉”该字符串不需要被复制。

const char* foo = "c-string"; 
boost::const_string bar(foo); // will copy foo 
boost::const_string baz(boost::ref(foo)); // assumes foo will always be a valid pointer. 
1

如果用户创建一个const对象从字符串则没有理由复制传递本地字符串,并且因为他不会作出任何操作,他会做的唯一的事情就是让字符串大小,字符串搜索和其他不会改变字符串的函数。

哦,是的。只是它通过作为 const并不意味着它实际上是构造函数调用之外的const,并且它并不意味着它在字符串对象仍然存在时不会被销毁。函数参数的关键字const只意味着函数不会修改或删除它(试图实现修改const参数的函数将导致编译器错误),但函数无法知道外部发生了什么。