(type&name) 和 (type* name) 参数定义之间有什么区别?

发布于 2024-07-23 07:45:04 字数 385 浏览 9 评论 0原文

这是一个非常基本的问题,但仍然很高兴听到 C++ 专家的意见。

在 C++ 中声明引用参数有两种非常相似的方法。

1) 使用“星号”:

void DoOne(std::wstring* iData);

2) 使用“&”:

void DoTwo(std::wstring& iData);

每种方法的含义是什么? 无论如何,有什么陷阱吗?

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

好处#2:std::wstring 是故意使用的。 在每种情况下对标准库类有何影响?

A very basic question, but still, it would be good to hear from C++ gurus out there.

There are two rather similar ways to declare by-reference parameters in C++.

1) Using "asterisk":

void DoOne(std::wstring* iData);

2) Using "ampersand":

void DoTwo(std::wstring& iData);

What are implications of each method?
Are there any gotcha's in any case?

Bonus #1: What would be a formal way to call method in #1 and #2? Are they both called "by-reference"?

Bonus #2: std::wstring is used deliberately. What would be implications towards standard library classes in each case?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

断肠人 2024-07-30 07:45:05

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

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

Rule number one for this: If NULL is a valid value for the function parameter in the context of the function, then pass it as pointer, otherwise pass it as reference.

Rationale, if it cannot (should not!) ever be NULL, then don't put yourself through the trouble of checking for NULL.

深者入戏 2024-07-30 07:45:05

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

它们每个的结果都非常相似:对内存中对象的引用最终位于方法的范围内。 它们似乎都没有严格的内存要求。 该对象可以位于堆栈中,也可以位于堆中。

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

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

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

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

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

While writing examples, I came up with my own answer. Anything other than below?

The result of each of them is quite similar: a reference to an object in the memory ends up within method's scope. There seem to be no strict memory requirements for any of them. The object can be either on stack or in heap.

In case of stack each of the methods would be called like this:

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

Yet, when it comes to the heap, the second approach would require that the object must exist before calling the method. If the object does not exist, the caller would cause exception, not the callee.

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

In the above, if out-of-memory condition occurs and pData ends up NULL, the crash would happen before DoTwo, but DoOne would swallow the NULL and might crash some time later.

惟欲睡 2024-07-30 07:45:05

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

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

I wouldnt call myself a C++ gure (except for on my CV), but i'd say; unless theres any use of passing the parameter as a pointer (i.e the function wants to check for null), always use a reference.

That also goes for functions returning objects, returning a pointer is somehow telling the user of the class that it might be null.

一枫情书 2024-07-30 07:45:05

在 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
}

In DoOne, iData can be assigned NULL. If you use that after calling DoOne, the application will crash.

Something like

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

and

{
    std::wstring* pData = new std::wstring();
    DoOne(pData);
    pData->someFunction(); //Crash
}
伴我心暖 2024-07-30 07:45:05

当您说以下内容时,您的答案是完全错误的:

每一个的结果都相当
类似:对对象的引用
内存最终在方法内
范围。 好像没有严格规定
其中任何一个的内存要求。

connsider:

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

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

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

这里 r 没有自己的存在,它只是一个引用。 我把它带到哪里
地址 我正在获取 r 所指事物的地址。

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

Your answer is completely wrong when you say:

The result of each of them is quite
similar: a reference to an object in
the memory ends up within method's
scope. There seem to be no strict
memory requirements for any of them.

connsider:

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

here p1 has a definite "memory requirement" - it must exist and I must be able to take its address. Contrast this with

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

here r has no existence of its own, it is merely a reference. Whem I take its
address I am taking the address of the thing that r refers to.

Your remarks regarding the NULL pointer are also mistaken. Derefrencing the NULL pointer causes undefined behaviour - this may or may not result in a crash.

绅士风度i 2024-07-30 07:45:05

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

If you write a function that gets a variable by pointer, you'll most probably have to check if the pointer is valid (eg not NULL), else you risk program crash.

诠释孤独 2024-07-30 07:45:04

#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
}

#1 uses a pointer parameter ('passing a pointer to'), #2 uses a reference parameter ('passing by reference'). They are very similar, but note that the calling code looks different in the two cases:

std::wstring s;

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

Some people prefer #1, using a convention that passing by pointer indicates that the function might change the value of s (even though either function could). Other people (myself included) prefer #2, since passing by reference does not allow NULL to be passed.

There is another important difference when passing by const pointer or reference. A temporary variable can only be passed to a const reference parameter:

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
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文