5

一个非常基本的问题,但仍然很高兴听到 C++ 大师的来信。

在 C++ 中,有两种相当相似的方式来声明引用参数。

1)使用“星号”:

void DoOne(std::wstring* iData);

2)使用“和”:

void DoTwo(std::wstring& iData);

每种方法的含义是什么?在任何情况下都有什么问题吗?

奖励 #1:在 #1 和 #2 中调用方法的正式方式是什么?它们都被称为“引用”吗?

奖励 #2:故意使用 std::wstring。在每种情况下对标准库类有什么影响?

4

7 回答 7

7

#1 使用指针参数('传递指针'),#2 使用引用参数('通过引用传递')。它们非常相似,但请注意,两种情况下的调用代码看起来不同:

std::wstring s;

DoOne(&s); // pass a pointer to s
DoTwo(s); // pass s by reference

有些人更喜欢#1,使用通过指针传递的约定表示函数可能会更改 s 的值(即使任何一个函数都可以)。其他人(包括我自己)更喜欢#2,因为通过引用传递不允许传递 NULL。

通过const指针或引用传递时还有另一个重要区别。临时变量只能传递给 const 引用参数:

void ByConstPointer(const std::wstring&);
void ByConstReference(const std::wstring*);

void test()
{
  ByConstPointer(&std::wstring(L"Hello")); // error: cannot take address of temporary
  ByConstReference(std::wstring(L"Hello")); // fine
}
于 2009-06-04T08:31:02.203 回答
2

规则一:如果 NULL 是函数上下文中函数参数的有效值,则将其作为指针传递,否则将其作为引用传递。

基本原理,如果它不能(不应该!)永远是 NULL,那么不要让自己经历检查 NULL 的麻烦。

于 2009-06-04T09:04:50.687 回答
1

在编写示例时,我想出了自己的答案。除了下面还有什么?

它们中的每一个的结果都非常相似:对内存中对象的引用最终在方法的范围内。它们中的任何一个似乎都没有严格的内存要求。对象可以在堆栈或堆中。

在堆栈的情况下,每个方法都将像这样调用:

{
    std::wstring data;
    DoOne(&data);
    DoTwo(data);
}

然而,当涉及到堆时,第二种方法要求对象在调用方法之前必须存在。如果对象不存在,调用者将导致异常,而不是被调用者。

{
    std::wstring* pData = new std::wstring();
    DoOne(pData);
    DoTwo(*pData);
}

在上面,如果出现内存不足的情况并且 pData 最终为 NULL,则崩溃会在 DoTwo 之前发生,但 DoOne 会吞下 NULL 并可能在一段时间后崩溃。

于 2009-06-04T06:51:32.733 回答
0

我不会称自己为 C++ 人物(除了我的简历),但我会说;除非有任何将参数作为指针传递的用途(即函数要检查空值),否则始终使用引用。

这也适用于返回对象的函数,返回指针以某种方式告诉类的用户它可能为空。

于 2009-06-04T07:01:25.553 回答
0

在 DoOne 中,可以将 iData 分配为 NULL。如果在调用 DoOne 后使用它,应用程序将崩溃。

就像是

void DoOne(std::wstring* iData)
{
   //Use iData
   delete iData;
   iData = NULL;
}

{
    std::wstring* pData = new std::wstring();
    DoOne(pData);
    pData->someFunction(); //Crash
}
于 2009-06-04T08:19:27.580 回答
0

当您说:

它们中的每一个的结果都非常相似:对内存中对象的引用最终在方法的范围内。它们中的任何一个似乎都没有严格的内存要求。

考虑:

void f( int * p1 ) {
   int ** p2 = & p1;
}

这里 p1 有一个明确的“内存要求”——它必须存在并且我必须能够获取它的地址。将此与

void f( int & r ) }
   int * p = & r;
}

这里 r 没有它自己的存在,它只是一个参考。当我取它的地址时,我取的是 r 所指事物的地址。

您对 NULL 指针的评论也是错误的。取消引用 NULL 指针会导致未定义的行为 - 这可能会也可能不会导致崩溃。

于 2009-06-04T08:30:34.513 回答
0

如果您编写一个通过指针获取变量的函数,您很可能必须检查指针是否有效(例如,不是 NULL),否则您将面临程序崩溃的风险。

于 2009-06-04T08:45:56.090 回答