string浅拷贝以及在dll中使用的注意事项

1.一个原则:某个模块中分配的空间就应该由它来释放!比如说在dll中分配的空间就应由这个dll来释放,而不应该有main来释放,因为dll中用来分配空间的环境可能和main中用来分配的环境不一样。关于这一点window核心编程中的dll里面进行了讲解,但是说真的我还是不明白为什么会这样。但是要记住这个原则!

2.mian 中的如下语句:
 string str1("l10");
 string str2("l10value");
 pi->addElement(str1, str2 );
//pi是指向dll提供的一个接口的指针。
dll中是如下实现addElement函数的:
bool *****::addElement(/*in*/string elementName,/*in*/string elementValue)
{
 //。。省略
 return true;//返回时对elementName,elementValue进行析构,这导致释放它们具体字符串的空间,
 //但是这些字符串的空间是在main 中分配的,所以出现运行时错误!!!(其实是无效内存访问)
}

3.解决方案:
对于上面这种情况我们只要把dll的改成引用就可以了:如下
bool *****::addElement(/*in*/string &elementName,/*in*/string &elementValue)
{
 return true;
}

4.反思:感觉把string用于dll并不是一个好主意。
前言:为什么要用浅拷贝。因为假如字符串空间很到的话,若不用浅拷贝则将非常费时且浪费空间。
1.string作为dll输出接口的方法的输入参数,这时可以作为引用来传递。这种情况下容易解决,如上。
这里是指dll中不会对string作任何改变。

2.dll输出接口的方法返回一个string,也就是字符串空间在dll中分配,让后在main中获得这个stirng,
则以为着在main中释放空间,但由于是浅拷贝,所以将出现错误。
dll中的代码如下:
string ****::getString()
{
 string s("abc");
 return s;
}
main中的代码如下:
main()
{
//省略。。
string strretdll= pi->getString();//
 return 0;//返回师调用string的析构函数,进而释放字符串空间,但由于这个空间不是在main模块中分配
 则导致错误。
}
好问题出来了:在getString返回时为什么不会把字符串空间析构掉呢? 事实上string的析构函数要调用一个称为
_Tidy(bool)的函数来处理。注意不同的stl实现如何析构string的具体方式是不一样的。总之经过我观察之后,在getString
返回时并不释放字符串空间,尽管执行了析构函数.我想这一点有点像智能指针。
对于这种情况的解决方法:
a.把空间分配和释放均在main中,但是main并不知道要具体分配多少空间
b.把空间分配和释放均在dll中, 但是如何才能在main中调用dll的方法来要求dll释放空间。
//现在该想到com中IUnknown的重要作用了吧!!!!

3.string作为dll输出接口的方法的输出参数。这种情况同样出现情况2的问题。

4.string作为dll输出接口的方法的输入输出参数。具有输出特性时和情况2相似。

思考:能不能用指向string的指针呢?

不方便!!

最后我下一个结论:在dll中string不能作为输出属性的参数!!
所以,我们只能显式地在dll中定义一个输出函数,用这个输出函数来释放dll分配的空间!!

不过也可以在VC工程中使用PROGECT--->SETTINGS 中,选择 C/C++  CATEGORY 选择 code generation 中 user run-time lib 选择 debug multithreanded ,这样也可以避免string 内存没有释放问题。建议一般不在动态链接库中返回 string

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 C++ string 类型是一个非常常用的字符类,可以方便地进行字符的操作。使用 string 类型需要注意以下几点: 1. 头文件:需要包含 <string> 头文件。 2. 声明:需要使用 std 命名空间,或者在全局范围内使用 using namespace std; 声明。 3. 初始化:可以直接使用字符字面量或者其他 string 对象初始化。 4. 操作:可以使用常规的字符操作,如比较、拼接、查找、替换等。 5. 长度:可以使用 size() 或者 length() 方法获取字符的长度。 6. 遍历:可以使用 for 循环或者迭代器遍历字符的每一个字符。 7. 转换:可以使用 c_str() 方法将 string 类型转换为 const char* 类型,或者使用 stoi()、stof() 等方法将 string 类型转换为其他类型。 示例代码: ``` #include <iostream> #include <string> using namespace std; int main() { string s1 = "hello"; string s2("world"); string s3 = s1 + " " + s2; cout << s3 << endl; if (s1 == "hello") { cout << "s1 equals to hello" << endl; } int index = s3.find("world"); if (index != string::npos) { cout << "world found at index " << index << endl; } for (char c : s3) { cout << c << " "; } cout << endl; const char* cstr = s3.c_str(); cout << "cstr: " << cstr << endl; return 0; } ``` 输出结果: ``` hello world s1 equals to hello world found at index 6 h e l l o w o r l d cstr: hello world ``` 需要注意的是,string 类型的底层实现是动态分配的内存,因此在进行大量字符操作时需要注意内存的使用。同时,由于 string 对象的复制和传递会涉及到内存的拷贝,因此也需要注意效率问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值