std::string 作为成员函数的参数的奇怪行为
Strange behavior of std::string as an argument of a member function
我有一个类:
class MyClass
{
char *filename1;
char *filename2;
public:
void setFilename1(std::string str)
{
filename1 = const_cast<char*>(str.c_str())
}
void setFilename2(std::string str))
{
filename2 = const_cast<char*>(str.c_str())
}
void function()
{
// do semthing
}
void printFilename1()
{
std::cout<<filename1<<std::endl;
}
}
这是我的主要功能:
MyClass *p = new MyClass();
p->setFilename1("first_string");
p->printFilename1();
p->setFilename2("second_string");
p->printFilename1();
输出对我来说非常令人惊讶:
first_string
second_string
我发誓我的函数MyClass::setFilename2没有错别字,我没有两次设置文件名2变量。
我使用的是 g++ 编译器版本 4.8.4。以下是我编译类的方法:
g++ -g -O -Wall -fPIC -pthread -std=c++11 -Wno-deprecated-declarations -m64 -I/home/user/root-6.06.00/include -c myClass.cxx
现在,另一个惊喜:当我更改MyClass::setFilename函数时:
void setFilename2(char* str))
{
filename2 = str;
}
我得到了我期望的输出:
first_string
first_string
执行函数 MyClass::function() 不会更改任何字符串的值。
这到底是怎么回事呢?这与我对C++的了解相矛盾。如果一个函数不引用相同的变量并且彼此无关,它们如何对另一个函数产生影响?
我想这可能与编译器版本或某些编译器选项有关。但我不知道发生了什么。
编辑:你能向我解释为什么这段代码的行为方式吗?
c_str()
返回指向char
数组的指针,只要std::string
不被修改,该数组就保持有效;在您的情况下,您调用c_str()
的std::string
对象在方法返回后立即被销毁(它是从字符串文本动态创建的临时对象),因此您有效地存储了指向已解除分配的内存的指针。当您执行printFileName1
时看到新值的事实只是分配器正在回收之前用于其他字符串的内存位置这一事实的副作用;就标准而言,这一切都是未定义的行为(您可以预期悲剧性的崩溃)。
正确的方法是将std::string
直接存储在类中,它将在MyClass
实例的整个生命周期内正确管理自己的内存。
class MyClass
{
std::string filename1;
std::string filename2;
public:
void setFilename1(std::string str)
{
filename1 = str;
}
void setFilename2(std::string str))
{
filename2 = str;
}
void function()
{
// do semthing
}
void printFilename1()
{
std::cout<<filename1<<std::endl;
}
}
MyClass *p;
p->setFilename1("first_string");
p->printFilename1();
p->setFilename2("second_string");
p->printFilename1();
你永远不会为 p 指向的内容分配内存,因此您在 *p 上调用的任何内容都将是未定义的行为
我认为这也是错误的。
void setFilename1(char* str)
{
std::string buf = str;
filename1 = const_cast<char*>(buf.c_str())
}
因为"buf"被删除在范围之外。
这没关系。
void setFilename1(std::string str)
{
static std::string buf = str;
filename1 = const_cast<char*>(buf.c_str())
}
其他方法:
class MyClass
{
char *filename1;
char *filename2;
public:
void setFilename1(std::string& str)
{
filename1 = const_cast<char*>(str.c_str())
}
void setFilename2(std::string& str))
{
filename2 = const_cast<char*>(str.c_str())
}
void function()
{
// do semthing
}
void printFilename1()
{
std::cout<<filename1<<std::endl;
}
}
MyClass *p = new MyClass();
string str1 = "first_string";
p->setFilename1(str1);
p->printFilename1();
string str2 = "second_string";
p->setFilename2(str2);
p->printFilename1();
delete p;
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 使用指向成员的指针将成员函数作为参数传递
- 如何将lambda作为模板类的成员函数参数
- 将成员函数指针作为参数传递给模板方法
- c++构造函数成员初始化:传递参数
- 使用带有 ref 参数的成员函数创建线程时出现编译错误
- 如何将成员函数作为回调参数传递给需要"typedef-ed"自由函数指针的函数?
- 模板化检查是否存在带有参数列表的类成员函数?
- 如何将类成员方法的参数列表自动填充写入可变参数?
- 为什么我需要在成员发起器列表中重复基类的模板参数?
- C++向量默认为成员参数
- 将成员函数作为构造函数参数调用时出错 "Variable is not a type name"
- 可变参数模板参数扩展 类型为 std::function 的类成员
- 绑定到可变参数成员函数
- C/C++ 包含点的宏参数(成员访问运算符)
- 将const char * const参数成员分配给新值
- 基于模板参数成员函数参数的模板专用化
- 如何访问可变参数成员
- 可变类参数成员变量的异构存储
- 非模板类中的可变参数成员