我的背景是使用更多托管语言(C#、python),但我在C/C++方面越来越有经验。我熟悉为什么通过引用进行选择(.)和通过指针操作进行选择(->)运算符不同。在我遇到的所有情况下,如果你使用了不正确的一个,它将导致编译错误。如果是这样的话,他们为什么没有成为一个操作员?是否存在在同一对象上使用任意一个都会产生不同、有意义和有用的结果的情况?
这个问题的灵感来源于这个答案:这是用c++调用函数的正确方法吗?
在C++中,您可以重载->
-运算符,它几乎在所有智能指针实现中都使用。然而,其中一些也有自己的方法,即发布引用。
struct test {
int x;
};
std::shared_ptr<int> ptr(new test);
// Write to member x of the allocated object
ptr->x = 3;
// Reset the shared pointer to point to a different object.
// If there are no further shared_ptrs pointing to the previously allocated one,
// it is deleted.
ptr.reset(new test)
此外,编译器将运算符-.
解析为类似多级指针(即test*** ptr
)的内容会非常混乱。按照您的逻辑,ptr.x
、(*ptr).x
、(**ptr).x
和(***ptr).x
都是相同的。
不能将->
应用于对基本类型的引用,也不能将.
应用于指针,但可以将两者应用于用户定义的类型,它们将具有不同的含义。最简单的例子是智能指针,如std::shared_ptr
:
struct A { int x; };
std::shared_ptr<A> p(new A);
p->x = 10;
p.reset();
是否存在通过引用选择元素和通过指针操作选择元素都有效的情况?
由于您可以在C++中重载operator->()
,因此您实际上可以在同一对象上互换使用->
和.
。你甚至可以设计一些东西,这样你就会得到不同的结果,就像这个例子:
#include <iostream>
struct Bar
{
void hello() const { std::cout << "Bar!!!n"; }
};
struct FooBar
{
Bar bar;
void hello() const { std::cout << "FooBar!!!n"; }
const Bar* operator->() const {return &bar; }
};
int main()
{
FooBar fb;
fb->hello();
fb.hello();
}
当然,在真正的代码中,你永远不会做像这样疯狂的事情(尽管我在"生产"代码中见过这种事情)。
简短的答案是一个智能指针
您可以使用"."访问智能指针类参数(如果您创建自己的智能指针类,则可以从中提取当前引用计数),而您可以使用"->"运算符访问使用智能指针存储的任何内容。