Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 通过隐式转换为char*(C+;+;)实现字符串类_C++_String_C++11_Casting - Fatal编程技术网

C++ 通过隐式转换为char*(C+;+;)实现字符串类

C++ 通过隐式转换为char*(C+;+;)实现字符串类,c++,string,c++11,casting,C++,String,C++11,Casting,根据我在几个地方读到的内容(这可能是std::string还没有这么做的原因),这可能是不可取的,但是在受控环境中,经过仔细使用,我认为可以编写一个字符串类,当第三方库方法(只使用char*作为参数)需要时,该类可以隐式转换为适当的可写char缓冲区,并且其行为仍然像具有Find()、Split()、SubString()等方法的现代字符串等。虽然我以后可以尝试实现通常的其他字符串操作方法,但我首先想问一下如何高效、安全地完成这项主要任务。目前,我们必须分配一个char数组,其大小大约为第三方方

根据我在几个地方读到的内容(这可能是std::string还没有这么做的原因),这可能是不可取的,但是在受控环境中,经过仔细使用,我认为可以编写一个字符串类,当第三方库方法(只使用char*作为参数)需要时,该类可以隐式转换为适当的可写char缓冲区,并且其行为仍然像具有Find()、Split()、SubString()等方法的现代字符串等。虽然我以后可以尝试实现通常的其他字符串操作方法,但我首先想问一下如何高效、安全地完成这项主要任务。目前,我们必须分配一个char数组,其大小大约为第三方方法所期望的char*输出的最大大小,将其传递给第三方方法,然后将返回的char*转换为std::string,以便能够使用它允许的方便方法,然后再次使用string.c_str()将其(const char*)结果传递给另一个方法。这既冗长又使代码看起来有点凌乱

以下是我迄今为止的初步实施:

MyString.h

#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
不能保证存储在单个连续内存块中,因此必须通过