请参阅以下代码。在此代码中,我将const char*
返回的test.c_str()
存储到引用中。我的问题是 - data
是否正确引用test
的内容?我认为test.c_str()
返回的ptr将是一个临时的,如果我将它绑定到引用,那么引用将无效。
我的想法是否正确?
class RefPtrTest
{
std::string test;
StoringClass storingClass;
public:
RefPtrTest(): test("hello"), storingClass(test.c_str())
{
}
}
其中StoringClass是
class StoringClass
{
const char*& data;
public:
StoringClass (const char*& input): data(input)
{
}
}
EDIT1:
我们不要考虑std :: string正在做什么。假设我使用自己的名为mystring的类
class RefPtrTest
{
const mystring test;
StoringClass storingClass;
public:
RefPtrTest(): test("hello"), storingClass(test.getInternalPointer())
{
}
}
getInternalPointer
直接返回内部指针。我想验证这个假设,storingClass(test.getInternalPointer())
由test.getInternalPointer()
返回的ptr将是临时的,如果我将它绑定到引用将无效的引用。我的想法是否正确?
EDIT2:
StoringClass不受我的控制。基本上它是一个模板类,它存储对类型的引用。我将它用于const char*
。我知道你提出的所有设计问题。但是我不能改变那个类,我必须将它用于const char *
。除此之外别无他法。
答案 0 :(得分:3)
是的,你的想法是正确的(test.c_str()
返回一个temp,所以你不能用它来初始化一个引用),除非test.c_str()
实际上返回一个指针的引用,我不知道我认为它确实......是吗?
这应该会给你一个编译错误,但是,你试过吗?
在这种特殊情况下,实际使用指针进行某些操作并没有多大意义。但是如果你只是询问对指针的引用,那么你是正确的(无论类型如何)。
答案 1 :(得分:3)
该标准对c_str
(21.3.6 / 2)
要求:程序不得更改 存储在数组中的任何值。 程序也不应该对待 返回值作为有效指针 任何后续调用a后的值 类的非const成员函数 basic_string指定相同的 这是对象。
所以答案是否定的,你不能将指针视为对字符串内容的引用(在任何非const函数调用字符串之后)。
答案 2 :(得分:1)
如果您正在尝试这样做,则不应直接修改字符串缓冲区。
当您处理指针时,如果要更改指针类型所包含的地址,则只需要对指针的引用。如果您只想更改缓冲区,则只需存储char *。
如果你想访问这样的缓冲区,请使用std :: vector,而不是这样:
std::vector<char> v;
v.resize(size);
strcpy(&v.front(), "testing");
答案 3 :(得分:1)
请参阅以下有关cplusplus.com中std :: string c_str()成员函数的注释:
返回的数组指向一个内部位置,该位置具有此字符序列所需的存储空间加上其终止的空字符,但此数组中的值不应在程序中修改,只能保持不变,直到接下来调用字符串对象的非常量成员函数。
虽然您没有在发布的代码中调用任何非const成员函数,但这不是一个好主意。在RefPtrTest类中修改私有std :: sting测试变量时,会无意中影响StoringClass类(这违反了RefPtrTest的封装)。有些人以后维护你的代码(也许你)可能没有意识到这一点,并引入了一个错误/崩溃。
答案 4 :(得分:1)
如果StoringClass需要对指针的引用,那么你必须确保有一个指针供它引用(并修改,因为它不是一个const引用),其生命周期与引用的生命周期一样长。 :
#include <string>
#include <iostream>
template <typename T>
class StoringClass {
T& data;
public:
StoringClass (T& input): data(input) { }
void print() const { std::cout << data << "\n"; }
void set(T x) { data = x; }
};
class RefPtrTest {
const std::string test;
const char *ptr;
StoringClass<const char*> storingClass;
public:
RefPtrTest(): test("hello"), ptr(test.c_str()), storingClass(ptr) { }
void print() const { storingClass.print(); }
void set(const char* x) { storingClass.set(x); }
};
int main() {
RefPtrTest t;
t.print();
t.set("world");
t.print();
}
输出:
hello
world
IMO StoringClass有点奇怪。例如,我也可以标记set
函数const
,它仍然有效。但是如果你必须使用它,你必须使用它。如果您可以使用StoringClass<const char *const>
,那可能会更好:它将确保您不会调用任何修改指针的StoringClass函数。你问这个问题的方式表明你不希望这种情况发生。
编辑:
如果test
不是const,那么RefPtrTest可以有一个函数:
void set_another_way(const char *x) { test = x; set(test.c_str()); }
哪个会修改字符串并更新指向storingClass
的指针。函数体等同于test = x; ptr = test.c_str();
。假设单线程代码也解决了test.c_str()
返回的指针值有效性的任何问题,前提是set_another_way
是test
被修改的唯一方法。
坦率地说,StoringClass
不应该被称为StoringClass
。它不存储任何东西;-p
答案 5 :(得分:-1)
可能有效。但是,您不应该依赖此行为。
string
类实现下面有char*
,c_str()
方法可能只返回指向该数组开头的指针。但是,随着字符串随时间的变化,此内部数组可能会在内存中移动,无论如何都会调整大小。每次您要将c_str()
转换为string
时,都应调用char*
。
它可能只返回指向内部存储器的指针,所以无论如何都非常快。