C++ 通过隐式转换为char*(C+;+;)实现字符串类
根据我在几个地方读到的内容(这可能是std::string还没有这么做的原因),这可能是不可取的,但是在受控环境中,经过仔细使用,我认为可以编写一个字符串类,当第三方库方法(只使用char*作为参数)需要时,该类可以隐式转换为适当的可写char缓冲区,并且其行为仍然像具有Find()、Split()、SubString()等方法的现代字符串等。虽然我以后可以尝试实现通常的其他字符串操作方法,但我首先想问一下如何高效、安全地完成这项主要任务。目前,我们必须分配一个char数组,其大小大约为第三方方法所期望的char*输出的最大大小,将其传递给第三方方法,然后将返回的char*转换为std::string,以便能够使用它允许的方便方法,然后再次使用string.c_str()将其(const char*)结果传递给另一个方法。这既冗长又使代码看起来有点凌乱 以下是我迄今为止的初步实施: MyString.hC++ 通过隐式转换为char*(C+;+;)实现字符串类,c++,string,c++11,casting,C++,String,C++11,Casting,根据我在几个地方读到的内容(这可能是std::string还没有这么做的原因),这可能是不可取的,但是在受控环境中,经过仔细使用,我认为可以编写一个字符串类,当第三方库方法(只使用char*作为参数)需要时,该类可以隐式转换为适当的可写char缓冲区,并且其行为仍然像具有Find()、Split()、SubString()等方法的现代字符串等。虽然我以后可以尝试实现通常的其他字符串操作方法,但我首先想问一下如何高效、安全地完成这项主要任务。目前,我们必须分配一个char数组,其大小大约为第三方方
#pragma once
#include<string>
using namespace std;
class MyString
{
private:
bool mBufferInitialized;
size_t mAllocSize;
string mString;
char *mBuffer;
public:
MyString(size_t size);
MyString(const char* cstr);
MyString();
~MyString();
operator char*() { return GetBuffer(); }
operator const char*() { return GetAsConstChar(); }
const char* GetAsConstChar() { InvalidateBuffer(); return mString.c_str(); }
private:
char* GetBuffer();
void InvalidateBuffer();
};
示例用法(main.cpp)
#包括“MyString.h”
#包括
void testSetChars(字符*名称)
{
如果(!name)
返回;
//我们不知道这个长度,但知道最大长度
//每个函数的返回长度都是已知的。
char str[]=“随机名称”;
strcpy_s(姓名,strlen(str)+1,str);
}
int main(int,char*)
{
MyString cs(“测试初始值设定项”);
如果我没弄错你的意思,你想让它起作用:
mystring foo;
c_function(foo);
// use the filled foo
使用c_函数
像
void c_function(char * dest) {
strcpy(dest, "FOOOOO");
}
相反,我建议如下():
模板
结构字符串填充符{
字符数据[max+1];
std::字符串和目的地;
字符串填充符(std::string&d):目的地(d){
数据[0]='\0';//偏执狂
}
~string_filler(){
目的地=数据;
}
运算符char*(){
返回数据;
}
};
并且像这样使用它:
std::string foo;
c_function(string_filler<80>{foo});
std::stringfoo;
c_函数(字符串_填充{foo});
通过这种方式,可以为C函数提供一个“普通”缓冲区,缓冲区的最大值由您指定(您应该知道任何一种方式……否则调用函数都是不安全的)。销毁临时缓冲区时(根据标准,临时缓冲区必须发生在函数调用的表达式之后),会复制字符串(使用std::string
赋值运算符)放入由std::string
管理的缓冲区
回答您的问题:
你认为在这里使用向量而不是char*有什么主要的优点/缺点吗
是的:使用矢量可以让你从手动内存管理中解放出来。这是一个巨大的专业
我计划稍后向它添加宽字符支持。您认为两个结构的并集:{char,string}和{wchar_t,wstring}是实现这一目的的方法吗(一次只能是这两个结构中的一个)
联合是一个坏主意。你如何知道哪个成员当前处于活动状态?你需要联合之外的一个标志。你真的希望每个字符串都携带这个标志吗?相反,看看标准库在做什么:它使用模板来提供这个抽象
这是不是太过分了
编写字符串类?是的,太多了。如果我理解正确,您希望它起作用:
mystring foo;
c_function(foo);
// use the filled foo
使用c_函数
像
void c_function(char * dest) {
strcpy(dest, "FOOOOO");
}
相反,我建议如下():
模板
结构字符串填充符{
字符数据[max+1];
std::字符串和目的地;
字符串填充符(std::string&d):目的地(d){
数据[0]='\0';//偏执狂
}
~string_filler(){
目的地=数据;
}
运算符char*(){
返回数据;
}
};
并且像这样使用它:
std::string foo;
c_function(string_filler<80>{foo});
std::stringfoo;
c_函数(字符串_填充{foo});
通过这种方式,可以为C函数提供一个“普通”缓冲区,缓冲区的最大值由您指定(您应该知道任何一种方式……否则调用函数都是不安全的)。销毁临时缓冲区时(根据标准,临时缓冲区必须发生在函数调用的表达式之后),会复制字符串(使用std::string
赋值运算符)放入由std::string
管理的缓冲区
回答您的问题:
你认为在这里使用向量而不是char*有什么主要的优点/缺点吗
是的:使用矢量可以让你从手动内存管理中解放出来。这是一个巨大的专业
我计划稍后向它添加宽字符支持。您认为两个结构的并集:{char,string}和{wchar_t,wstring}是实现这一目的的方法吗(一次只能是这两个结构中的一个)
联合是一个坏主意。你如何知道哪个成员当前处于活动状态?你需要联合之外的一个标志。你真的希望每个字符串都携带这个标志吗?相反,看看标准库在做什么:它使用模板来提供这个抽象
这是不是太过分了
编写字符串类?是的,太多了。您想要做的事情已经存在。例如,使用这个普通的旧C函数:
/**
* Write n characters into buffer.
* n cann't be more than size
* Return number of written characters
*/
ssize_t fillString(char * buffer, ssize_t size);
从C++11开始:
std::string str;
// Resize string to be sure to have memory
str.resize(80);
auto newSize = fillSrting(&str[0], str.size());
str.resize(newSize);
或者不首先调整大小:
std::string str;
if (!str.empty()) // To avoid UB
{
auto newSize = fillSrting(&str[0], str.size());
str.resize(newSize);
}
但是在C++11之前,std::string
不能保证存储在单个连续内存块中
std::vector<char> v;
// Resize string to be sure to have memor
v.resize(80);
ssize_t newSize = fillSrting(&v[0], v.size());
std::string str(v.begin(), v.begin() + newSize);
std::vector v;
//调整字符串大小以确保有内存
v、 调整大小(80);
ssize_t newSize=fillSrting(&v[0],v.size());
std::string str(v.begin(),v.begin()+newSize);
您可以轻松地将它与Daniel的命题一起使用,您想做的事情已经存在。例如,使用这个简单的旧C函数:
/**
* Write n characters into buffer.
* n cann't be more than size
* Return number of written characters
*/
ssize_t fillString(char * buffer, ssize_t size);
从C++11开始:
std::string str;
// Resize string to be sure to have memory
str.resize(80);
auto newSize = fillSrting(&str[0], str.size());
str.resize(newSize);
或者不首先调整大小:
std::string str;
if (!str.empty()) // To avoid UB
{
auto newSize = fillSrting(&str[0], str.size());
str.resize(newSize);
}
但是在C++11之前,std::string
不能保证存储在单个连续内存块中,因此必须通过