我最近阅读了关于pointers to data structures的C ++教程的一部分,其结构定义为:
struct movies_t {
string title;
int year;
};
movies_t * pmovie;
它提到了(*pmovie).title
与*(pmovie.title)
的不同之处。有人能解释一下原因吗?
答案 0 :(得分:2)
你不能只是交换那种语法,因为两者都意味着不同的东西。
第一种情况,(*pmovie).title
表示pmovie是一个指针,你正在取消引用它,然后提取"标题"该对象的字段。等效/更简单的语法是pmovie-> title。
你的第二个案例说," Pmovie是一个对象,而title是指向某个东西的指针。我想取消引用该指针。"
例如:
struct Movie {
std::string title;
};
Movie movie;
Movie * pmovie = &movie; // here pmovie is a pointer to a movie
pmovie->title = "Trading Places";
(*pmovie).title = "Trading Places"; // same meaning as line above
VS
struct Movie {
std::string * title;
};
std::string title;
Movie pmovie; // here "pmovie" is an insanely named variable for a non-ptr
pmovie.title = &title;
*(pmovie.title) = "V For Vendetta"; // Note, pmovie not a ptr, title is
显然,第二种情况是荒谬的,实际上是一个糟糕的界面(你不希望你的对象界面中有原始指针,无论是内部还是外部拥有对象。)我只给出了示例来说明它们之间的区别是。希望您只在第一种情况下遇到代码。
答案 1 :(得分:1)
第一个取消引用指针pmovie
。它相当于
pmovie->title
第二种是非法语法,假设pmovie
是一个指针。
答案 2 :(得分:1)
如果pmovie
是指针(例如movies_t * pmovie
),则访问其成员必须使用->
- 运算符(即pmovie->title
)或取消引用指针为了使用.
- 符号(即(*pmovie).title
,相当于pmovie->title
)来解决它。相比之下,*(pmovie.title)
完全错误,因为运算符.
无法应用于指针。
答案 3 :(得分:0)
在C ++中,就像在数学中一样,复杂表达式的操作按特定顺序进行评估。操作的顺序通常会改变表达式的含义。括号可用于明确指定预期的顺序。例如,RegisterAsmPrinter
和$(document).on('click', '.ck-editor__editable_inline', function(e) {
// do something
})
。
1 + (2 * 3) == 1 + 6 == 7
与(1 + 2) * 3 == 3 * 3 == 9
不同,因为括号会更改操作的顺序。第一个间接(==取消引用)表达式(*pmovie).title
,并访问间接结果的成员*(pmovie.title)
。第二个访问表达式pmovie
的成员title
并指向该成员。
现在,鉴于声明title
,表达式pmovie
格式错误,因为成员访问运算符无法应用于指针。
答案 4 :(得分:0)
当你说(* pmovie).title时,这意味着你首先得到pmovie指向的内容,然后询问它的标题是什么。
当你说*(pmovie.title)时,你首先要求获得电影的标题,然后询问它指向的是什么。第二个是错误的,因为你不能问指针它的标题是什么,因为它只是一个指针,而不是一个真正的movies_t对象。
注意:这仅适用于您发布的特定示例。有时*(pmovie.title)有意义。考虑你有
的情况struct movies_t {
// note how I made title a string pointer, not just a string
string* title;
int year;
};
int main(){
// note that movie_object is NOT a pointer, so *movie_object makes no
// sense
movies_t movie_object;
// the following expects a string, but 'title' is a string pointer
// so movie_object.title returns a string pointer. I use * to access the
// actual string
cout << *(movie_object.title) << endl;
}
答案 5 :(得分:0)
它与operator precedence有关。这里,我们讨论的2个运算符是*
(解除引用运算符,也称为间接运算符)和.
(结构/类成员访问运算符)。它们必须以正确的顺序执行,否则你得到的结果没有意义。
让我们试试一个例子。你去游泳池。你穿上你的泳衣,把所有的东西都放在一个储物柜里,你可以拿一把钥匙上的钥匙。该号码指的是储物柜,并允许您识别它。在某种程度上,它“指向”储物柜(就像指针指向一个变量)。
现在,你即将游泳,你意识到你已经忘记了游泳帽。你记得你把它留在了储物柜里面的顶部抽屉里。因此,您必须:读取钥匙上的数字以找到您的储物柜(并打开它),然后打开顶部抽屉并带上泳帽。如果相反,你取了钥匙的号码,试图打开它的顶部抽屉(是的,钥匙的号码的顶部抽屉!),期望在里面找到一个游泳帽,然后试图读取帽子上的数字以找到它是否有用你的储物柜?当然不是。这没有意义。这意味着执行正确的操作,但是顺序错误,因此错误的对象。
现在,回到你的例子。 pmovie
是指向结构的指针。在我们讨论的两个操作(取消引用和成员访问)中,您希望取消引用它以获取结构。您当然不希望访问其中一个成员,因为指针不包含成员而不是键的编号
有抽屉。
同样,struct有成员,在这种情况下,一个名为title
。一旦你到了结构(储物柜),你想要访问它的内容(成员title
,或带游泳帽的抽屉)。
所以,我们想要做的是清楚:首先我们想要取消引用指针(比如读取键上的数字并找到锁定器),然后,对此操作的结果(结构或锁定器) ),我们想要拿出我们需要的东西(标题或顶部抽屉)。
现在回到C ++:如果你只是写*pmovie.title
,你会先执行什么操作,使用*
取消引用,或使用.
取消成员访问?请注意,您想要的并不一定是您得到的。在这种情况下,它不是:根据C ++的规则,必须首先评估点,因为它具有更高的优先级(为了避免每次都检查表,一个简单的助记符规则就是右边的那个,比如点,优先级比左边的优先级更高。这将导致一个没有意义的操作。
为了确保正确的结果,必须按正确的顺序应用运算符:首先是指针取消引用,获取结构,然后应用成员访问权限。为了确保这一点,我们必须强制编译器按照非默认顺序评估运算符,并且执行此操作的方法是使用括号:通过编写(*pmovie).title
,星点在点之前应用,这给出了预期的结果。