我有一个第三方库,它使用char*(非const)作为字符串值的占位符.为这些数据类型赋值的正确和安全的方法是什么?我有以下测试基准测试,它使用我自己的计时器类来测量执行时间:
#include "string.h"
#include <iostream>
#include <sj/timer_chrono.hpp>
using namespace std;
int main()
{
sj::timer_chrono sw;
int iterations = 1e7;
// first method gives compiler warning:
// conversion from string literal to 'char *' is deprecated [-Wdeprecated-writable-strings]
cout << "creating c-strings unsafe(?) way..." << endl;
sw.start();
for (int i = 0; i < iterations; ++i)
{
char* str = "teststring";
}
sw.stop();
cout << sw.elapsed_ns() / (double)iterations << " ns" << endl;
cout << "creating c-strings safe(?) way..." << endl;
sw.start();
for (int i = 0; i < iterations; ++i)
{
char* str = new char[strlen("teststr")];
strcpy(str, "teststring");
}
sw.stop();
cout << sw.elapsed_ns() / (double)iterations << " ns" << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
creating c-strings unsafe(?) way...
1.9164 ns
creating c-strings safe(?) way...
31.7406 ns
Run Code Online (Sandbox Code Playgroud)
虽然"安全"的方式摆脱了编译器的警告,但根据这个基准测试,它使代码大约慢了15-20倍(每次迭代1.9纳秒,每次迭代31.7纳秒).什么是正确的方式,以及那种"弃用"的方式是如此危险?
And*_*rei 10
C++标准很明确:
普通的字符串文字具有类型"n const char的数组"(C++ 11中的2.14.5.8节).
和
尝试修改字符串文字的效果是未定义的(C++ 11中的第2.14.5.12节).
对于编译时已知的字符串,获得a的安全方法non-const char*
就是这样
char literal[] = "teststring";
Run Code Online (Sandbox Code Playgroud)
你可以安全地
char* ptr = literal;
Run Code Online (Sandbox Code Playgroud)
如果在编译时你不知道字符串但知道它的长度你可以使用数组:
char str[STR_LENGTH + 1];
Run Code Online (Sandbox Code Playgroud)
如果您不知道长度,那么您将需要使用动态分配.确保在不再需要字符串时释放内存.
这仅在API未获得char*
您通过的所有权时才有效.
如果它试图在内部解除分配字符串,那么它应该在文档中说明并告知您分配字符串的正确方法.您需要将分配方法与API内部使用的方法相匹配.
该
char literal[] = "test";
Run Code Online (Sandbox Code Playgroud)
将创建一个带有automatinc存储的本地5字符数组(意味着当执行离开声明变量的作用域时,该变量将被销毁)并使用字符't','e','初始化数组中的每个字符. s','t'和'\ 0'.
您可以稍后编辑这些字符: literal[2] = 'x';
如果你这样写:
char* str1 = "test";
char* str2 = "test";
Run Code Online (Sandbox Code Playgroud)
然后,取决于编译器,str1
并且str2
可以是相同的值(即,指向相同的字符串).
("是否所有字符串文字都是不同的(即存储在非重叠对象中)是实现定义的."在C++标准的2.14.5.12节中)
它们也可能存储在内存的只读部分中,因此任何修改字符串的尝试都将导致异常/崩溃.
它们实际上也是这种类型const char*
:
char*str ="test";
实际上抛弃了字符串上的常量,这就是编译器发出警告的原因.
不安全的方法是在编译时知道所有字符串的方法.
你的"安全"方式会泄漏记忆,而且非常可怕.
通常你会有一个理智的C API接受const char *
,所以你可以在C++中使用适当的安全方式,即std::string
它的c_str()
方法.
如果您的C API承担字符串的所有权,那么您的"安全方式"还有另一个缺陷:您不能混合使用,new[]
并且free()
将使用C++ new[]
运算符分配的内存传递给期望调用free()
它的C API 是不允许的.如果C API不想free()
稍后调用该字符串,那么new[]
在C++端使用它应该没问题.
此外,这是C++和C的奇怪混合.
归档时间: |
|
查看次数: |
7785 次 |
最近记录: |