为什么在 C++ 中需要通过引用传递指针来更改指向的内容?
Why in C++ do I need to pass a pointer by reference to change the pointed content?
我正在编写一个函数来从着色器代码文件加载文本。我偶然发现了关于指针的一些奇怪的东西,我不知道为什么。
我有一个名为 Load 的函数。在此函数中,我将从文件流中获取的文本复制到 output 变量中。
static void Load(const GLchar* source_path, GLchar* output,GLint& count )
{
string code;
// loading logic here
code= vShaderStream.str(); // copying the string from the stream
count = code.length();
output = new GLchar[count];
std::size_t length = code.copy(output, count, 0);
output[length]= '[=10=]';
}
Load是这样调用的:
for (size_t i = 0; i < d_n_fragment; i++)
{
Load(d_fragment_source_path, d_fragment_code[i], d_fragment_string_count[i]);
}
其中d_fragment_code是已经初始化的Glchar**的双指针。在调用 Load 函数后,指针 d_fragment_code[i] 不包含文本。我尝试将 Load 函数的签名更改为:
static void Load(const GLchar* source_path, GLchar*& output,GLint& count )
从而通过引用传递指针。它的工作原理是在调用函数 d_fragment_code 后正确保存从文件加载的文本,但我不明白为什么要通过引用传递指针。
我认为只传递一个指针就足以改变它的内容。我很困惑,你能解释一下吗?
I thought that passing a pointer only would suffice to change its content.
传递指针足以改变指针对象(指向的东西)的内容。太棒了,它与传递引用的效果基本相同。
但你没有那样做。你想改变指针本身。
考虑一下,如果您想将一个对象传递给一个函数,以便该函数更改原始对象。让我们调用对象的类型 T,并假设它有一个成员函数 mutate
以某种方式改变它(这样我们就不必给出一个真实世界的例子作为 T
改变) :
void foo(T& handle)
{
handle.mutate();
}
void bar(T* handle)
{
handle->mutate();
}
int main()
{
T obj;
foo(obj);
bar(&obj);
}
foo
和 bar
完成同样的事情,分别使用引用和指针。
现在我们可以将此逻辑应用于任何事物,只需将各种类型交换为 T
。 你想到的场景是通过指针传递一些非指针对象来改变它:
void bar(int* handle)
{
handle->mutate();
}
int main()
{
int obj;
bar(&obj);
}
但是你 实际上 的情况要求 T
本身是一个指针,并使用 foo
而不是 bar
.这是可以理解的,这是令人困惑的!
void foo(GLint*& handle)
{
handle.mutate();
}
int main()
{
GLint* obj;
foo(obj);
}
如果有帮助,您还可以写成:
void bar(GLint** handle)
{
handle->mutate();
}
int main()
{
GLint* obj;
bar(&obj);
}
这实际上是等价的。
(免责声明:我没有在任何这些示例中初始化 obj
。你会想要的。)
output = new GLchar[count];
这会改变 output
指向的内容。如果您确定 output
已经指向足够大小的缓冲区,请删除此行。
如果必须修改指针而不是指针指向的对象,则应通过引用传递指针。
使用双指针也是类似的情况
这里有更详细的文章:
http://www.codeproject.com/Articles/4894/Pointer-to-Pointer-and-Reference-to-Pointer
我正在编写一个函数来从着色器代码文件加载文本。我偶然发现了关于指针的一些奇怪的东西,我不知道为什么。
我有一个名为 Load 的函数。在此函数中,我将从文件流中获取的文本复制到 output 变量中。
static void Load(const GLchar* source_path, GLchar* output,GLint& count )
{
string code;
// loading logic here
code= vShaderStream.str(); // copying the string from the stream
count = code.length();
output = new GLchar[count];
std::size_t length = code.copy(output, count, 0);
output[length]= '[=10=]';
}
Load是这样调用的:
for (size_t i = 0; i < d_n_fragment; i++)
{
Load(d_fragment_source_path, d_fragment_code[i], d_fragment_string_count[i]);
}
其中d_fragment_code是已经初始化的Glchar**的双指针。在调用 Load 函数后,指针 d_fragment_code[i] 不包含文本。我尝试将 Load 函数的签名更改为:
static void Load(const GLchar* source_path, GLchar*& output,GLint& count )
从而通过引用传递指针。它的工作原理是在调用函数 d_fragment_code 后正确保存从文件加载的文本,但我不明白为什么要通过引用传递指针。
我认为只传递一个指针就足以改变它的内容。我很困惑,你能解释一下吗?
I thought that passing a pointer only would suffice to change its content.
传递指针足以改变指针对象(指向的东西)的内容。太棒了,它与传递引用的效果基本相同。
但你没有那样做。你想改变指针本身。
考虑一下,如果您想将一个对象传递给一个函数,以便该函数更改原始对象。让我们调用对象的类型 T,并假设它有一个成员函数 mutate
以某种方式改变它(这样我们就不必给出一个真实世界的例子作为 T
改变) :
void foo(T& handle)
{
handle.mutate();
}
void bar(T* handle)
{
handle->mutate();
}
int main()
{
T obj;
foo(obj);
bar(&obj);
}
foo
和 bar
完成同样的事情,分别使用引用和指针。
现在我们可以将此逻辑应用于任何事物,只需将各种类型交换为 T
。 你想到的场景是通过指针传递一些非指针对象来改变它:
void bar(int* handle)
{
handle->mutate();
}
int main()
{
int obj;
bar(&obj);
}
但是你 实际上 的情况要求 T
本身是一个指针,并使用 foo
而不是 bar
.这是可以理解的,这是令人困惑的!
void foo(GLint*& handle)
{
handle.mutate();
}
int main()
{
GLint* obj;
foo(obj);
}
如果有帮助,您还可以写成:
void bar(GLint** handle)
{
handle->mutate();
}
int main()
{
GLint* obj;
bar(&obj);
}
这实际上是等价的。
(免责声明:我没有在任何这些示例中初始化 obj
。你会想要的。)
output = new GLchar[count];
这会改变 output
指向的内容。如果您确定 output
已经指向足够大小的缓冲区,请删除此行。
如果必须修改指针而不是指针指向的对象,则应通过引用传递指针。
使用双指针也是类似的情况
这里有更详细的文章:
http://www.codeproject.com/Articles/4894/Pointer-to-Pointer-and-Reference-to-Pointer