如何将 std::string 作为构造函数参数传递,并将其保存的 C 字符串存储在 void 指针中?
How do I pass a std::string as a constructor argument and store the C string it holds in a void pointer?
我有一个构造函数,它接受对std::string
对象的const
引用,并且应该将std::string
的内部C字符串存储在void
指针成员变量中。但是,当使用void
指针时,我的程序会出现段错误,并且gdb
说指针指向地址0x01
。这是我的消息来源:
噗
:class Foo {
public:
Foo(const std::string& str);
void* getData();
private:
Foo(void* newData);
void* data;
};
福.cpp:
Foo::Foo(const std::string& str)
: Foo(str.c_str())
{
//nothing
}
void* Foo::getData() {
return data;
}
Foo::Foo(void* newData)
: data(newData)
{
//nothing
}
主.cpp:
int func(void* data);
int main() {
Foo f("bar");
func(f.getData()); //segfault here
return 0;
}
int func(void* data) {
std::string str = (char*)data;
std::cout << str << std::endl;
return 0;
}
调用f.getData()
时,由"bar"
构造的字符串不再存在,因此指向其内部字符数组的指针不再有效。该字符串只是为函数调用构造的,并在执行main
-function 的其余部分之前再次析构。 取消引用无效指针时会发生段错误。
请尝试以下操作:
const std::string str("bar");
Foo f(str);
这样,当需要数据时,字符串仍在范围内。
除此之外,整体方法不可取。如果可能的话,最好不要使用void*
指针和原始指针,或者至少在对象中安全地管理它们。您的问题已经清楚地说明了为什么这种指针使用不安全且容易出错。
Foo f("bar"(;
您正在将对临时值的引用传递给构造函数。对象的生存期仅在构造函数内。因此,空白*数据指向已删除的内存。
更准确地说,如果您不知道,您可能想知道l值和r 值在C++中的区别。
例如(int a = 5
这里a是 l 值,5是 r 值。简单地说,它们是数据类型的值类别。
https://en.cppreference.com/w/cpp/language/value_category
切勿存储对 r 值的引用。在执行任何操作之前,请始终检查对象的生存期,并确保对象在操作完成之前保持活动状态。
溶液
string a = "bar";
Foo foo(a);
这里 a 是 l 值。但用户有责任确保a 的生命范围不仅仅是foo。
或更好
string a = "bar";
{
Foo foo(a);
}
通过这种方式,您可以确保在
代码崩溃和烧毁的原因是
: Foo(str.c_str())
正在呼叫
Foo(const std::string& str);
而不是
Foo(void* newData);
所以你有无限递归。这一切都很糟糕,我建议您重新考虑您的方法,但是只是为了让它运行,请明确void *
str.c_str()
:
: Foo((void *)str.c_str())
当然,将"bar"作为一个独立的string
以避免处理临时变量,并将字符串传递给构造函数。这样,指针将一直有效,直到包含string
的范围结束。
演示:https://ideone.com/v7YfBX
首先,我建议不要使用 void* 在极少数情况下,需要使用 void*,并且会丢失任何有用的类型信息。
如果要直接在 std::string 对象中操作位,则从 C++ 17 开始,字符串上的 data 方法可以直接访问字符,而不是常量。
如果你想让你的代码更安全,只需将std::string存储为Foo类的成员变量,并使用你可用的方法。 这也意味着您无需手动跟踪从c_str或数据方法调用传递的字符串的内部指针。
例如(部分示例(
class Foo {
public:
Foo(const std::string& str);
const char* getData() const;
char* getData();
private:
std::string m_str;
};
Foo::Foo(const std::string& str)
: m_str(str)
{
}
const char* Foo::getData() const
{
return m_str.c_str();
}
char* Foo::getData()
{
// Note: Need C++ 17
return m_str.data();
}
- 将字符串存储在c++中的稳定内存中
- 当字符串存储在变量中时,如何将字符串转换为wchar_t
- 将字符串存储到文件下一行的变量中
- 将字符串存储在 constexpr 结构中
- 将字符串存储为十六进制而不进行转换
- 如何将 std::string 作为构造函数参数传递,并将其保存的 C 字符串存储在 void 指针中?
- 将非数字字符串存储为二进制整数
- 将 C++ 字符串存储到 char* 向量中
- C++无法将对齐的字符串存储在字符串变量中并打印出来
- 短(ASCII,每个字符 7 位)字符串存储和C++中的比较优化
- 我无法将 Excel 中的输入字符串存储为二维字符串
- 如何将此字符串存储为不同的变量
- C 将字符串存储到类中
- C :占用更多内存,将单个字符作为char或字符串存储
- 排序通过字符串C 存储在向量的对象
- 如何将可变长度字符串存储在C/C 中
- 将字符串存储在无符号长整型的向量中
- 如何使用模板解码将来自 YAML::Node 的字符串存储在类中
- 将字符串存储到数组中
- C++-将用逗号分隔的用户输入字符串存储到向量中