gpt4 book ai didi

c++ - 如何分配字符串文字

转载 作者:行者123 更新时间:2023-11-30 03:33:26 24 4
gpt4 key购买 nike

我是一名 Java 程序员;我上一次写 C 或 C++ 是在 20 年前。现在我回来了,我正在尝试使用更现代的 C++,例如 C++11/C++14,并避免使用旧的 C 风格编程。

如何分配一个字符串,就像在 Java 中一样:

private static final String MY_STRING = "Hello World"; // could also be public

现在我有了对文本 "Hello World" 的引用 MY_STRING,我可以在我的程序中使用任意多次,如果我愿意的话将其更改为说 "Hello Dolly",我完全在一个地方进行更改。

我想在 C++ 中实现相同的目标。示例:

JavaVMOption* options = new JavaVMOption[1];

options[0].optionString = (char *)"-Djava.class.path=.";

这行得通,没有更多的问题,但我不喜欢它,因为只有在需要时才能在一个地方更改它。所以,我声明(甚至在头文件中):

std::string classpath = "-Djava.class.path=.";
// or
const std::string classpath = "-Djava.class.path=.";

我将它用作:

options[0].optionString = (char *)classpath.c_str();

现在,使用 c_str() 函数,这也有效,但我又回到了普通的旧 C!

我真的很想知道是否有办法保持更现代的 C++ 级别?

是的,我知道,

JavaVMOption* options = new JavaVMOption[1]; 

已按原样声明,我无法更改它。但即使在 C++ 中,在给定的情况下使用引用而不是指针也是一个好主意,就像在 Java 中一样。有解决办法吗?我找不到。

最佳答案

"Hello" 是 6 个 charH e l< 的 const 缓冲区 l o \0 分别是整个程序的生命周期。

std::string bob = "Hello";

将该缓冲区复制到 std::string 对象中。 std::string 是一个值语义对象;这是 Java 往往缺乏的东西,因为所有对象都在各处通过引用隐式传递。

options[0].optionString = (char *)"-Djava.class.path=.";

这是非常危险的。您将该缓冲区转换为指向 char 的非 const 指针,然后将其分配给 optionString

我不知道 optionString 是什么,但如果它是一个类型为 char* 的变量,这会让您面临未定义的行为。对缓冲区 "-Djava.class.path=." 的任何编辑都是未定义的行为,并且将非 const 指针存储到此类缓冲区只是乞求发生。

简而言之,optionString 的类型是决定其危险程度的关键。仅仅是鲁莽,还是真的很愚蠢?

JavaVMOption* options = new JavaVMOption[1];

这会在堆上创建一个大小为 1JavaVMOption 数组,然后将指向第一个元素的指针存储在 options 中。

这里有很多没有意义的东西。销毁它需要将其作为数组销毁?

JavaVMOption options;

这会在堆栈上创建一个名为 optionsJavaVMOption。它会在范围结束时自动销毁。这似乎更实用。除非您需要 new,否则使用 new 没有意义,而且在 C++ 中您很少需要 new

我找到了一些示例代码:

#include <jni.h>       /* where everything is defined */
...
JavaVM *jvm; /* denotes a Java VM */
JNIEnv *env; /* pointer to native method interface */
JavaVMInitArgs vm_args; /* JDK/JRE 6 VM initialization arguments */
JavaVMOption* options = new JavaVMOption[1];
options[0].optionString = "-Djava.class.path=/usr/lib/java";
vm_args.version = JNI_VERSION_1_6;
vm_args.nOptions = 1;
vm_args.options = options;
vm_args.ignoreUnrecognized = false;
/* load and initialize a Java VM, return a JNI interface
* pointer in env */
JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
delete options;
/* invoke the Main.test method using the JNI */
jclass cls = env->FindClass("Main");
jmethodID mid = env->GetStaticMethodID(cls, "test", "(I)V");
env->CallStaticVoidMethod(cls, mid, 100);
/* We are done. */
jvm->DestroyJavaVM();

而且这不是由以 C++ 编程为生的人编写的。

这是我最初的尝试:

struct destroy_java_vm {
void operator()(JavaVM* jvm)const{
jvm->DestroyJavaVM();
}
};
using up_java_vm = std::unique_ptr< JavaVM, destroy_java_vm >;

struct java_vm {
up_java_vm vm;
JNIEnv* env = 0;
};
struct java_vm_option {
std::string string;
std::shared_ptr<void> extra_info;
};
using java_vm_options = std::vector<java_vm_option>;

struct java_vm_init {
unsigned version = JNI_VERSION_1_2;
java_vm_options options;
bool ignore_unrecognized = false;
java_vm init() {
std::vector<JavaVMOption> java_options(options.size());
for (std::size_t i = 0; i < options.size(); ++i) {
java_options[i].optionString = &options.string[0];
java_options[i].extraInfo = options.extra_info.get();
}
JavaVMInitArgs args;
args.version = version;
args.options = java_options.data();
args.nOptions = java_options.size();
args.ignoreUnrecognized = ignore_unrecognized?TRUE:FALSE;
java_vm retval;
JavaVM* tmp = 0;
auto res = JNI_CreateJavaVM(&tmp, (void **)&retval.env, &args);
if (res < 0) {
return {}; // error message? How?
}
retval.vm.reset( tmp );
return retval;
}
}

使用:

java_vm_init init;
init.options.push_back("-Djava.class.path=.");
auto vm = init.init();
if (!vm.env) { return /* error case */; }
/* invoke the Main.test method using the JNI */
jclass cls = vm.env->FindClass("Main");
jmethodID mid = vm.env->GetStaticMethodID(cls, "test", "(I)V");
vm.env->CallStaticVoidMethod(cls, mid, 100);
/* We are done. */

根据我对 unique_ptr 的使用,java_vm 对象是一种只能移动的值类型。销毁时,java vm 会自动销毁(如果您没有将其移出)。

当直接与 API 对话时,我们必须转向 C 风格代码,因为许多跨语言 API 都是使用 C 风格接口(interface)编写的。我们将该 C 风格的接口(interface)包装在更安全、更易于使用的 C++ 类型中。

代码未经测试,可能包含拼写错误。

关于c++ - 如何分配字符串文字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42930922/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com