&-运算符/ C++,解释
&-Operator/ C++, Explanation
如果有人简单地向我解释如何 recognised/understood,我将不胜感激,何时应该使用 & 运算符。
作为参考:
& Address-of
和
The address of a variable can be obtained by preceding the name of a
variable with an ampersand sign (&), known as address-of operator. For
example:
foo = &myvar;
This would assign the address of variable myvar to foo; by preceding
the name of the variable myvar with the address-of operator (&), we
are no longer assigning the content of the variable itself to foo, but
its address.
但是一切对我来说都太抽象了。
例如这里:
当我们在主函数中生成整数时,为什么是
if (!myDoc.setContent(&file, errorMsg, errorLine)) {
假的?
//这里是代码行->
QString errorMsg;
int errorLine;
QString errorMsg;
int errorLine;
if (!myDoc.setContent(&file, &errorMsg, &errorLine)) {
...
}
以及如何在这里识别例如
QString maxString(const QString& s, int len)
应该使用而不是
QString maxString(const QString s, int len)
//这里保留第二个例子
QString maxString(const QString& s, int len) {
if (s.size() < len) return s;
else return s.left(len)+"...";
}
void showTree(QTextStream& out, const QDomNode& node, const int intent) {
QString text;
if (node.nodeType() == QDomNode::ElementNode) {
...
}
} else if (node.nodeType() == QDomNode::TextNode) {
text = node.nodeValue().trimmed();
if (text.isEmpty()) return; // keine Ausgabe leerer Textknoten
text = "#text: "+maxString(text, 20);
}
...
}
&
在变量声明中使用与在代码中使用时不同(我指的是运行的部分)。
在运行代码中,可以理解为"an address of"。所以
int i = 7;
std::cout << i; // output: 7
std::cout << &i; // output: 0x7fff2af8900 (or any other, mostly random, hex number)
&i
输出的数字是一个地址,变量存放的地方。变量的地址可以以多种方式使用(主要是在称为指针算术的东西中)。例如,根据语言的定义,内存中的数组是顺序连续存储的。因此,int i[4];
定义了 4
int
的数组,它们在内存中像盒子一样并排存储。您可以使用 i[1]
来访问该数组的第二个成员,并且 i
(没有 []
)保存第一个成员的地址。
因此 i == &i[0]
对于数组总是正确的。
但是,在声明中,它是一个叫做引用的东西。
int value = 7;
int& ref = value; // with this, you can look at value using ref variable
value = 8;
std::cout << ref; // output: 8
编辑:
当调用带有参数的函数时,它的所有参数都会被复制,并且您的函数使用它自己的数据。如果你有看起来像 bool check_validity(LargeData data)
的函数,它以某种方式处理大量的 LargeData
然后 returns true
如果数据有效,否则 false
。您实际上是将整串数据复制到该函数中。在该函数的 return 之后,副本丢失了。现在,复制是(时间)昂贵的,如果你不需要那个副本,你为什么要复制它。如果您使用引用传递 LargeData
包(如 LargaData&
或更好的 const LargeData&
以禁用不需要的修改),唯一实际复制的是一些常量指针(很可能 8Bytes
) 而不是整个数据(可能是 10MB 或 500GB 甚至更多)。
所以 关于你的代码 QString maxString(const QString& s, int len)
是因为你不想花时间复制 s
输入变量如果你只想阅读它的内容。
现在,myDoc.setContent(&file, &errorMsg, &errorLine)
可能是某个函数(使用某些规则)如果成功则填充 file
和 returns true
,否则为 false,并且如果它是假的,它还会用一些失败的信息填充 errorMsg
和 errorLine
。但是,我们如何定义该函数才能拥有那么多输出变量。很简单,我们将变量的地址传递给该函数,它会写入该地址。
这些是 &
运算符的两种不同用途:
首先使用,在if (!myDoc.setContent(&file, errorMsg, errorLine))
,&
运算符returns地址文件对象的。在这种情况下,需要 & 因为 setContent()
函数可能已声明为:
setContent(FileType * inputFile, ..., ...);
在声明函数时,使用 *
运算符意味着您将收到一个 地址 作为参数。在这种情况下,inputFile
需要一个内存地址,并且通过说 &file
您将 file
的内存地址作为参数传递。
第二次使用&
运算符是在函数声明中。通过在函数声明中使用 & 运算符,您希望通过引用 传递对象。如果您还不知道,您应该查看参数传递 按值 或 按引用.
之间的区别
简而言之,按值传递参数意味着您将传递对象的副本,因此传递的对象在函数调用后不会被修改。通过引用传递值意味着该函数将能够修改传递的对象。
示例:
void maxString(QString& s, int len) // s passed by reference
{
s = QString::ToUpper(s, len); // Just made that up
}
QString myString = "My string";
maxString(myString, myString.length());
// myString is now "MY STRING"
void maxString(QString s, int len) // s passed by value
{
s = QString::ToUpper(s, len); // Just made that up
}
QString myString = "My string";
maxString(myString, myString.length());
// myString is still "My string"
在 C++ 中,按值传递或按引用传递之间还有其他差异。
基本上,按值传递意味着您将为传递的对象创建一个 copy,有效地为此调用 copy 构造函数目的。这在大多数情况下是不希望的,因为它无缘无故地使用 CPU 时间。为了克服这个问题,使用 const ClassName &
。这意味着您将传递对对象的常量引用(即不会在复制构造函数中浪费时间)并且函数将无法修改对象。
你应该查一下传递 value/reference 和使用 const 之间的区别。
如果有人简单地向我解释如何 recognised/understood,我将不胜感激,何时应该使用 & 运算符。
作为参考:
& Address-of
和
The address of a variable can be obtained by preceding the name of a variable with an ampersand sign (&), known as address-of operator. For example:
foo = &myvar;
This would assign the address of variable myvar to foo; by preceding the name of the variable myvar with the address-of operator (&), we are no longer assigning the content of the variable itself to foo, but its address.
但是一切对我来说都太抽象了。
例如这里: 当我们在主函数中生成整数时,为什么是
if (!myDoc.setContent(&file, errorMsg, errorLine)) {
假的?
//这里是代码行->
QString errorMsg;
int errorLine;
QString errorMsg;
int errorLine;
if (!myDoc.setContent(&file, &errorMsg, &errorLine)) {
...
}
以及如何在这里识别例如
QString maxString(const QString& s, int len)
应该使用而不是
QString maxString(const QString s, int len)
//这里保留第二个例子
QString maxString(const QString& s, int len) {
if (s.size() < len) return s;
else return s.left(len)+"...";
}
void showTree(QTextStream& out, const QDomNode& node, const int intent) {
QString text;
if (node.nodeType() == QDomNode::ElementNode) {
...
}
} else if (node.nodeType() == QDomNode::TextNode) {
text = node.nodeValue().trimmed();
if (text.isEmpty()) return; // keine Ausgabe leerer Textknoten
text = "#text: "+maxString(text, 20);
}
...
}
&
在变量声明中使用与在代码中使用时不同(我指的是运行的部分)。
在运行代码中,可以理解为"an address of"。所以
int i = 7;
std::cout << i; // output: 7
std::cout << &i; // output: 0x7fff2af8900 (or any other, mostly random, hex number)
&i
输出的数字是一个地址,变量存放的地方。变量的地址可以以多种方式使用(主要是在称为指针算术的东西中)。例如,根据语言的定义,内存中的数组是顺序连续存储的。因此,int i[4];
定义了 4
int
的数组,它们在内存中像盒子一样并排存储。您可以使用 i[1]
来访问该数组的第二个成员,并且 i
(没有 []
)保存第一个成员的地址。
因此 i == &i[0]
对于数组总是正确的。
但是,在声明中,它是一个叫做引用的东西。
int value = 7;
int& ref = value; // with this, you can look at value using ref variable
value = 8;
std::cout << ref; // output: 8
编辑:
当调用带有参数的函数时,它的所有参数都会被复制,并且您的函数使用它自己的数据。如果你有看起来像 bool check_validity(LargeData data)
的函数,它以某种方式处理大量的 LargeData
然后 returns true
如果数据有效,否则 false
。您实际上是将整串数据复制到该函数中。在该函数的 return 之后,副本丢失了。现在,复制是(时间)昂贵的,如果你不需要那个副本,你为什么要复制它。如果您使用引用传递 LargeData
包(如 LargaData&
或更好的 const LargeData&
以禁用不需要的修改),唯一实际复制的是一些常量指针(很可能 8Bytes
) 而不是整个数据(可能是 10MB 或 500GB 甚至更多)。
所以 关于你的代码 QString maxString(const QString& s, int len)
是因为你不想花时间复制 s
输入变量如果你只想阅读它的内容。
现在,myDoc.setContent(&file, &errorMsg, &errorLine)
可能是某个函数(使用某些规则)如果成功则填充 file
和 returns true
,否则为 false,并且如果它是假的,它还会用一些失败的信息填充 errorMsg
和 errorLine
。但是,我们如何定义该函数才能拥有那么多输出变量。很简单,我们将变量的地址传递给该函数,它会写入该地址。
这些是 &
运算符的两种不同用途:
首先使用,在if (!myDoc.setContent(&file, errorMsg, errorLine))
,&
运算符returns地址文件对象的。在这种情况下,需要 & 因为 setContent()
函数可能已声明为:
setContent(FileType * inputFile, ..., ...);
在声明函数时,使用 *
运算符意味着您将收到一个 地址 作为参数。在这种情况下,inputFile
需要一个内存地址,并且通过说 &file
您将 file
的内存地址作为参数传递。
第二次使用&
运算符是在函数声明中。通过在函数声明中使用 & 运算符,您希望通过引用 传递对象。如果您还不知道,您应该查看参数传递 按值 或 按引用.
简而言之,按值传递参数意味着您将传递对象的副本,因此传递的对象在函数调用后不会被修改。通过引用传递值意味着该函数将能够修改传递的对象。
示例:
void maxString(QString& s, int len) // s passed by reference
{
s = QString::ToUpper(s, len); // Just made that up
}
QString myString = "My string";
maxString(myString, myString.length());
// myString is now "MY STRING"
void maxString(QString s, int len) // s passed by value
{
s = QString::ToUpper(s, len); // Just made that up
}
QString myString = "My string";
maxString(myString, myString.length());
// myString is still "My string"
在 C++ 中,按值传递或按引用传递之间还有其他差异。
基本上,按值传递意味着您将为传递的对象创建一个 copy,有效地为此调用 copy 构造函数目的。这在大多数情况下是不希望的,因为它无缘无故地使用 CPU 时间。为了克服这个问题,使用 const ClassName &
。这意味着您将传递对对象的常量引用(即不会在复制构造函数中浪费时间)并且函数将无法修改对象。
你应该查一下传递 value/reference 和使用 const 之间的区别。