C++ 函数实参传递 (argument passing)

2023-11-15

C++ 函数实参传递 (argument passing)

argument [ˈɑːɡjumənt]:n. 实参
parameter [pəˈræmɪtə(r)]:n. 形参

每次调用函数时都会重新创建它的形参,并用传入的实参对形参进行初始化。形参初始化的机理与变量初始化一样。形参的类型决定了形参和实参交互的方式。如果形参是引用类型,它将绑定到对应的实参上;否则,将实参的值拷贝后赋给形参。

当形参是引用类型时,它对应的实参被引用传递 (passed by reference) 或者函数被传引用调用 (called by reference)。和其它引用一样,引用形参也是它绑定的对象的别名,引用形参是它对应的实参的别名。

当实参的值被拷贝给形参时,形参和实参是两个相互独立的对象。这样的实参被值传递 (passed by value) 或者函数被传值调用 (called by value)。

1. 传值参数 (passing arguments by value)

当初始化一个非引用类型的变量时,初始值被拷贝给变量。此时,对变量的改动不会影响初始值。

int n = 0;
int i = n;  // i is a copy of the value in n
i = 42;     // value in i is changed, n is unchanged

传值参数的机理完全一样,函数对形参做的所有操作都不会影响实参。

1.1. 指针形参

指针的行为和其它非引用类型一样。当执行指针拷贝操作时,拷贝的是指针的值。拷贝之后,两个指针是不同的指针。因为指针使我们可以间接地访问它所指的对象,所以通过指针可以修改它所指对象的值。

int n = 0, i = 42;
int *p = &n, *q = &i;  // p points to n, q points to i
*p = 42;               // value in n is changed, p is unchanged
p = q;                 // p now points to i, values in i and n are unchanged

指针形参的行为与之类似:

// function that takes a pointer and sets the pointed-to value to zero
void reset(int *ip) {
	*ip = 0;  // changes the value of the object to which ip points
	ip = 0;   // changes only the local copy of ip, the argument is unchanged (只改变了 ip 的局部拷贝,实参未被改变)
}

调用 reset 函数之后,实参所指的对象被置为 0,但是实参本身并没有改变:

#include <iostream>

// function that takes a pointer and sets the pointed-to value to zero
void reset(int *ip) {
	*ip = 0;  // changes the value of the object to which ip points (改变指针 ip 所指对象的值)
	ip = 0;   // changes only the local copy of ip, the argument is unchanged (只改变了 ip 的局部拷贝,实参未被改变)
}

int main() {
	int i = 42;
	reset(&i);  // changes i but not the address of i
	std::cout << "i = " << i << std::endl;  // prints i = 0

	return 0;
}

i = 0
请按任意键继续. . .

在 C++ 语言中,建议使用引用类型的形参替代指针。

2. 传引用参数 (passing arguments by reference)

对于引用的操作实际上是作用在引用所引的对象上:

int n = 0, i = 42;
int &r = n;  // r is bound to n (i.e. r is another name for n)
r = 42;      // n is now 42
r = i;       // n now has the same value as i
i = r;       // i has the same value as n

引用形参的行为与之类似。通过使用引用形参,允许函数改变一个或多个实参的值。

和其它引用一样,引用形参绑定初始化它的对象。当调用这一版本的 reset 函数时,val 绑定我们传给函数的实参对象,此时改变 val 也就是改变 val 所引对象的值。调用这一版本的 reset 函数时,我们直接传入对象而无须传递对象的地址:

#include <iostream>

// function that takes a reference to an int and sets the given object to zero
void reset(int &val) {
	// val is just another name for the object passed to reset
	val = 0;  // changes the value of the object to which val refers
}

int main() {
	int num = 42;
	reset(num);  // num is passed by reference, the value in num is changed
	std::cout << "num = " << num << std::endl;  // prints num = 0

	return 0;
}

num = 0
请按任意键继续. . .

在上述调用过程中,形参 val 仅仅是 num 的又一个名字。在 reset 内部对 val 的使用即是对 num 的使用。

2.1. 使用引用避免拷贝

拷贝大的类类型对象或者容器对象比较低效,甚至有的类类型 (包括 IO 类型在内) 根本就不支持拷贝操作。当某种类型不支持拷贝操作时,函数只能通过引用形参访问该类型的对象。

一个函数比较两个 std::string 对象的长度。因为 std::string 对象可能会非常长,所以应该尽量避免直接拷贝它们,这时使用引用形参是比较明智的选择。如果函数无须改变引用形参的值,最好将其声明为常量引用。

// compare the length of two strings
bool isShorter(const std::string &s1, const std::string &s2) {
	return s1.size() < s2.size();
}

2.2. 使用引用形参返回额外信息

一个函数只能返回一个值,然而有时函数需要同时返回多个值,引用形参为我们一次返回多个结果提供了有效的途径。

3. const 形参和实参 (const parameters and arguments)

顶层 (top-level) const 作用于对象本身。

const int ci = 42;   // we can not change ci, const is top-level
int i = ci;          // 正确: when we copy ci, its top-level const is ignored
int * const p = &i;  // const is top-level, we can not assign to p (const 是顶层的,不能给 p 赋值)
*p = 0;              // 正确: changes through p are allowed, i is now 0

当用实参初始化形参时会忽略顶层 const,形参的顶层 const 被忽略了。当形参有顶层 const 时,传给它常量对象或者非常量对象都是可以的。调用 fun 函数时,既可以传入 const int 也可以传入 int。

void fun(const int i) { /* fun can read but not write to i */ }

忽略掉形参的顶层 const 可能产生意想不到的结果:

void fun(const int i) { /* fun can read but not write to i */ }
void fun(int i) { /* . . . */ }  // error: redefines fun(int)

在 C++ 语言中,允许我们定义若干具有相同名字的函数,不过前提是不同函数的形参列表应该有明显的区别。因为形参的顶层 const 被忽略掉了,所以在上面的代码中传入两个 fun 函数的参数可以完全一样。因此第二个 fun 是错误的,尽管形式上有差异,但实际上它的形参和第一个 fun 的形参没什么不同。

3.1. const + 指针或引用形参

形参的初始化方式和变量的初始化方式是一样的,可以使用非常量初始化一个底层 const 对象,但是反过来不行;同时一个普通的引用必须用同类型的对象初始化。

int i = 42;
const int *cp = &i;  // 正确: but cp can't change i
const int &r = i;    // 正确: but r can't change i
const int &r2 = 42;  // 正确: C++ 允许我们用字面值初始化常量引用。
int *p = cp;         // 错误: types of p and cp don't match
int &r3 = r;         // 错误: types of r3 and r don't match
int &r4 = 42;        // 错误: can't initialize a plain reference from a literal (不能用字面值初始化一个非常量引用)

要想调用引用版本的 reset 函数,只能使用 int 类型的对象,而不能使用字面值、求值结果为 int 的表达式、需要转换的对象或者 const int 类型的对象。类似的,要想调用指针版本的 reset 函数只能使用 int*

// function that takes a reference to an int and sets the given object to zero
void reset(int &val) {
	// val is just another name for the object passed to reset
	val = 0;  // changes the value of the object to which val refers
}

// function that takes a pointer and sets the pointed-to value to zero
void reset(int *ip) {
	*ip = 0;  // changes the value of the object to which ip points
	ip = 0;   // changes only the local copy of ip, the argument is unchanged (只改变了 ip 的局部拷贝,实参未被改变)
}
int i = 0;
const int ci = i;
std::string::size_type ctr = 0;
reset(&i);   // calls the version of reset that has an int* parameter
reset(&ci);  // 错误: can't initialize an int* from a pointer to a const int object (不能用指向 const int 对象的指针初始化 int*)
reset(i);    // calls the version of reset that has an int& parameter
reset(ci);   // 错误: can't bind a plain reference to the const object ci (不能把普通引用绑定到 const 对象 ci 上)
reset(42);   // 错误: can't bind a plain reference to a literal (不能把普通应用绑定到字面值上)
reset(ctr);  // 错误: types don't match, ctr has an unsigned type (类型不匹配,ctr 是无符号类型)

3.2. 尽量使用常量引用

把函数不会改变的形参定义成 (普通的) 引用是一种比较常见的错误,这么做会给函数的调用者一种误导,即函数可以修改它的实参的值。此外,使用引用而非常量引用也会极大地限制函数所能接受的实参类型。不能把 const 对象、字面值或者需要类型转换的对象传递给普通的引用形参。(We can not pass a const object, or a literal, or an object that requires conversion to a plain reference parameter.)

#include <iostream>

// returns the index of the first occurrence of c in str (返回 str 中 c 第一次出现的位置索引)
// the reference parameter num counts how often c occurs (引用形参 num 负责统计 c 出现的总次数)
std::string::size_type find_char(const std::string &str, const char &c, std::string::size_type &num) {
	auto ret = str.size();  // position of the first occurrence, if any (如果有的话,第一次出现的位置)
	num = 0;                // set the occurrence count parameter
	for (decltype(ret) i = 0; i != str.size(); ++i) {
		if (str[i] == c) {
			if (ret == str.size()) {
				ret = i;    // remember the first occurrence of c (记录 c 第一次出现的位置)
			}
			++num;          // increment the occurrence count (出现的次数加 1)
		}
	}

	// count is returned implicitly in num (出现的次数通过 num 隐式地返回)
	return ret;
}

int main() {
	std::string str("yongqiang");
	size_t num = 0;

	auto index = find_char(str, 'g', num);
	std::cout << index << " -> " << num << std::endl;

	return 0;
}

3 -> 2
请按任意键继续. . .

find_char 函数正确地将它的 std::string 类型的形参定义成常量引用 (const std::string &)。假如我们把它定义成普通的 std::string &

std::string::size_type find_char(std::string &str, const char &c, std::string::size_type &num);

则只能将 find_char 函数作用于 std::string 对象,类似下面这样的调用

const std::string str("yongqiang");
size_t num = 0;
auto index = find_char(str, 'g', num);

将在编译时发生错误。

1>d:\vulkan_workspace\sample\sample\sample.cpp(24): error C2664: 'unsigned int find_char(std::string &,const char &,unsigned int &)': cannot convert argument 1 from 'const std::string' to 'std::string &'

假如其它函数正确地将它们的形参定义成常量引用,那么第二个版本的 find_char 无法在此类函数中正常使用。

bool is_sentence(const std::string &str) {
	// if there is a single period at the end of str, then str is a sentence (如果在 str 的末尾有且只有一个句号,则 str 是一个句子)
	std::string::size_type num = 0;
	return ((find_char(str, '.', num) == str.size() - 1) && (num == 1));
}

如果 find_char 的第一个形参类型是 std::string &,那么上面这条调用 find_char 的语句将在编译时发生错误。原因在于 str 是常量,但 find_char 被不正确地定义成只能接受普通引用。

解决该问题的一种思路是修改 is_sentence 的形参类型,但是这么做只不过转移了错误而已,结果是 is_sentence 函数的调用者只能接受非常量 std::string 对象了。正确的修改思路是改正 find_char 函数的形参。如果实在不能修改 find_char,就在 is_sentence 内部定义一个 std::string 类型的变量,令其为 str 的副本,然后把这个 std::string 对象传递给 find_char。

4. 数组形参 (array parameters)

数组的两个特殊性质对我们定义和使用作用在数组上的函数有影响,这两个性质分别是:不允许拷贝数组,使用数组时通常会将其转换成指针。因为不能拷贝数组,所以我们无法以值传递的方式使用数组参数。因为数组会被转换成指针,所以当我们为函数传递一个数组时,实际上传递的是指向数组首元素的指针。

尽管不能以值传递的方式传递数组,但是我们可以把形参写成类似数组的形式:

// each function has a single parameter of type const int* (每个函数都有一个 const int* 类型的形参)
void print(const int*);
void print(const int[]);    // shows the intent that the function takes an array (函数的意图是作用于一个数组)
void print(const int[10]);  // dimension for documentation purposes at best (这里的维度表示我们期望数组含有多少元素,实际不一定)

尽管表现形式不同,但上面的三个函数是等价的:每个函数的唯一形参都是 const int* 类型的。当编译器处理对 print 函数的调用时,只检査传入的参数是否是 const int* 类型:

int i = 0, j[2] = { 0, 1 };
print(&i);  // 正确: &i is int*
print(j);   // 正确: j is converted to an int* that points to j[0]

如果我们传给 print 函数的是一个数组,则实参自动地转换成指向数组首元素的指针,数组的大小对函数的调用没有影响。和其它使用数组的代码一样,以数组作为形参的函数也必须确保使用数组时不会越界。因为数组是以指针的形式传递给函数的,所以一开始函数并不知道数组的确切尺寸,调用者应该为此提供一些额外的信息。

4.1. 使用标记指定数组长度

管理数组实参的第一种方法是要求数组本身包含一个结束标记,使用这种方法的典型示例是 C 风格字符串。C 风格字符串存储在字符数组中,并且在最后一个字符后面跟着一个空字符。

函数在处理 C 风格字符串时遇到空字符停止:

// prints a null-terminated array of characters
void print(const char *cp) {
	if (cp) {
		// if cp is not a null pointer (若 cp 不是一个空指针)
		while (*cp) {
			// so long as the character it points to is not a null character (只要指针所指的字符不是空字符)
			std::cout << *cp++;  // print the character and advance the pointer (输出当前字符并将指针向前移动一个位置)
		}
	}
}

这种方法适用于那些有明显结束标记且该标记不会与普通数据混淆的情况,但是对于像 int 这样所有取值都是合法值的数据就不太有效了。

4.2. 使用标准库规范

管理数组实参的第二种技术是传递指向数组首元素和尾后元素的指针,这种方法受到了标准库技术的启发。

// print ints in the given range
void print(const int *beg, const int *end) {
	// print every element starting at beg up to but not including end (输出 beg 到 end 之间,不含 end 的所有元素)
	while (beg != end) {
		std::cout << *beg++ << " ";  // print the current element and advance the pointer (输出当前元素并将指针向前移动一个位置)
	}
}

while 循环使用解引用运算符和后置递减运算符输出当前元素并在数组内将 beg 向前移动一个元素,当 beg 和 end 相等时结束循环。

为了调用这个函数,我们需要传入两个指针:一个指向要输出的首元素,另一个指向尾元素的下一位置。

#include <iostream>

// prints a null-terminated array of characters
void print(const char *cp) {
	if (cp) {
		// if cp is not a null pointer (若 cp 不是一个空指针)
		while (*cp) {
			// so long as the character it points to is not a null character (只要指针所指的字符不是空字符)
			std::cout << *cp++;  // print the character and advance the pointer (输出当前字符并将指针向前移动一个位置)
		}
	}
}

// print ints in the given range
void print(const int *beg, const int *end) {
	// print every element starting at beg up to but not including end (输出 beg 到 end 之间,不含 end 的所有元素)
	while (beg != end) {
		std::cout << *beg++ << " ";  // print the current element and advance the pointer (输出当前元素并将指针向前移动一个位置)
	}
}

int main() {
	print("yongqiang!"); // calls first version of print
	std::cout << std::endl;

	// j is converted to a pointer to the first element in j (j 转换成指向它首元素的指针)
	// the second argument is a pointer to one past the end of j (第二个实参是指向 j 的尾后元素的指针)
	int j[2] = { 0, 1 };
	print(std::begin(j), std::end(j));  // library begin and end functions
	std::cout << std::endl;

	// equivalent call, directly calculate the begin and end pointers
	print(j, j + 2);
	std::cout << std::endl;

	return 0;
}

yongqiang!
0 1
0 1
请按任意键继续. . .

只要调用者能正确地计算指针所指的位置,那么上述代码就是安全的。在这里,我们使用标准库 begin 和 end 函数提供所需的指针。

4.3. 显式传递一个表示数组大小的形参

第三种管理数组实参的方法是专门定义一个表示数组大小的形参。

#include <iostream>

// "const int ia[]" is equivalent to "const int* ia"
// size is passed explicitly and used to control access to elements of ia
void print(const int ia[], size_t size) {
	for (size_t i = 0; i != size; ++i) {
		std::cout << ia[i] << std::endl;
	}
}

int main() {
	int j[] = { 0, 1 };  // int array of size 2

	print(j, std::end(j) - std::begin(j));

	return 0;
}

0
1
请按任意键继续. . .

这个版本的程序通过形参 size 的值确定要输出多少个元素,调用 print 函数时必须传入这个表示数组大小的值。只要传递给函数的 size 值不超过数组实际的大小,函数就是安全的。

4.4. 数组形参和 const

当函数不需要对数组元素执行写操作的时候,数组形参应该是指向 const 的指针。只有当函数确实要改变元素值的时候,才把形参定义成指向非常量的指针。

4.5. 数组引用形参 (array reference parameters)

C++ 语言允许将变量定义成数组的引用,基于同样的道理,形参也可以是数组的引用。此时,引用形参绑定到对应的实参上,也就是绑定到数组上。

// 正确: parameter is a reference to an array, the dimension is part of the type (形参是数组的引用,维度是类型的一部分)
void print(int (&arr)[10]) {
	for (auto elem : arr) {
		std::cout << elem << std::endl;
	}
}

&arr 两端的括号必不可少:

fun(int &arr[10])   // 错误: declares arr as an array of references
fun(int(&arr)[10])  // 正确: arr is a reference to an array of ten ints (arr 是具有 10 个整数的整型数组的引用)

因为数组的大小是构成数组类型的一部分,所以只要不超过维度,在函数体内就可以放心地使用数组。但是,这一用法也无形中限制了 print 函数的可用性,我们只能将函数作用于大小为 10 的数组。

int i = 0, j[2] = { 0, 1 };
int k[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
print(&i);  // 错误: argument is not an array of ten ints (实参不是含有 10 个整数的数组)
print(j);   // 错误: argument is not an array of ten ints (实参不是含有 10 个整数的数组)
print(k);   // 正确: argument is an array of ten ints (实参是含有 10 个整数的数组)

4.6. 传递多维数组

在 C++ 语言中实际上没有真正的多维数组,所谓多维数组其实是数组的数组。

和所有数组一样,当将多维数组传递给函数时,真正传递的是指向数组首元素的指针。因为我们处理的是数组的数组,所以首元素本身就是一个数组,指针就是一个指向数组的指针。数组第二维 (以及后面所有维度) 的大小都是数组类型的 一部分,不能省略。

// matrix points to the first element in an array whose elements are arrays of ten ints (matrix 指向数组的首元素,该数组的元素是由 10 个整数构成的数组)
void print(int (*matrix)[10], int rowSize) { /* . . . */ }

上述语句将 matrix 声明成指向含有 10 个整数的数组的指针。

再一次强调,*matrix 两端的括号必不可少:

int *matrix[10];    // array of ten pointers (10 个指针构成的数组)
int (*matrix)[10];  // pointer to an array of ten ints (指向含有 10 个整数的数组的指针)

我们也可以使用数组的语法定义函数,此时编译器会一如既往地忽略掉第一个维度,所以最好不要把它包括在形参列表内。

// equivalent definition (等价定义)
void print(int matrix[][10], int rowSize) { /* . . . */ }

matrix 的声明看起来是一个二维数组,实际上形参是指向含有 10 个整数的数组的指针。

下标引用 ([]) 优先级高于间接访问 (*)。

References

https://yongqiang.blog.csdn.net/
(美) Stanley B. Lippman, (美) Josée Lajoie, (美) Barbara E. Moo 著, 王刚, 杨巨峰 译. C++ Primer 中文版[M]. 第 5 版. 电子工业出版社, 2013.
https://www.informit.com/store/c-plus-plus-primer-9780321714114

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 函数实参传递 (argument passing) 的相关文章

  • C++ 析构函数和函数调用顺序

    假设我有以下代码片段 Foo foo return bar 现在 C 标准是否保证 bar 将在 foo Foo 之前调用 或者这是编译器 实现的选择 Thanks 这是有保证的行为 实际执行过程如下 0 enter block scope
  • C++ 令人头疼的命名空间

    好吧 这个问题已经发生了一些变化 我想尝试从我正在追求的基本目标开始 重新 创建在 C 资源获取和初始化中包装遗留 C 语言实体的库代码 并提供基本或更好的异常保证 使此代码的客户端能够以非常自然的 C 方式使用它 而不会为现有代码创建大量
  • 如何在 wpf 密码框设置一些默认文本? [复制]

    这个问题在这里已经有答案了 可能的重复 WPF 中的水印文本框 https stackoverflow com questions 833943 watermark textbox in wpf 我可以知道如何在 WPF 的密码框中放入一些
  • 获取 WSA 错误代码的格式化消息

    我在 win32 C 应用程序中使用winsock2 我将使用 MessageBox 显示可以通过调用 WSAGetLastError 检索的网络错误 我怎样才能做到这一点 我看到 FormatMessage 但我不明白如何使用它 例如 以
  • C# Socket.receive连续接收0字节且循环中不阻塞

    我正在尝试用 C 编写一个最简单的多线程 TCP 服务器 它接收来自多个客户端的数据 每次连接新客户端时 都会建立套接字连接 并将套接字作为参数传递给新类函数 之后运行 while 循环并接收数据 直到客户端连接为止 这里的问题是 sock
  • Windows Server / Datacenter:设置 CPU 关联性 > 64 个核心

    SetThreadAffinityMask 允许为 64 个逻辑核心 处理器 设置关联掩码 但是 Windows Datacenter 最多可以有 64 个 CPU 每个 CPU 都有多个内核 请参阅here http social tec
  • F1 2019 UDP解码

    我目前正在为 F1 方向盘开发自己的显示器 F1 2019 由codemasters提供 通过UDP发送数据 该数据存储在字节数组中 我在解码返回的数组时遇到一些问题 问题是我得到了很多信息 但我不知道如何处理它们 我将向您介绍我所尝试过的
  • 是否已经有一些基于 std::vector 的 set/map 实现?

    对于小型集合或地图 通常使用排序向量而不是基于树的向量要快得多set map 特别是对于 5 10 个元素的情况 LLVM 有一些类本着这种精神 http llvm org docs ProgrammersManual html ds se
  • 将 MyGeneration 与 Fluent NHibernate 结合使用

    我在这里找到了一个使用 MyGeneration 生成 NHibernate 代码的绝佳模板 http vucetica blogspot com 2009 01 nhibernate template for my Generation
  • 如何在 Xamarin.Forms 中强制使用浅色模式?

    我的应用程序的 UI 设计为在灯光模式下使用 但如果手机的默认主题是深色模式 我的应用程序也会切换到深色模式 并且 UI 看起来很垃圾 所以我想强制我的应用程序使用灯光模式 我怎样才能做到这一点 In my app xaml我使用的文件Us
  • 如何设置属性选择器的值 Expression>

    我需要使用模式工厂的想法将 Person 类实体中的实体属性 Address 与 FactoryEntities 类中的表达式 linq 相关联 看看这就是我所拥有的并且我想要做的 Address address new Address a
  • 在 WinForms 中显示输入对话框

    我想在我的 WinForm 应用程序中显示输入模式 我浏览过网络 但没有找到执行此操作的良好模式 我知道我必须创建另一个表单 并使用 ShowDialog 方法 你是对的 请注意 模式对话框在关闭时不会自动处理 与非模式对话框不同 因此您需
  • 如何创建 .bat 文件来运行 C# 代码?

    我需要的是 我有一个 C 代码 我想构建它以便在桌面上创建一个 bat 文件 因此 当我从桌面运行这个 bat 文件时 它应该执行 C 代码 有没有办法在编译之前更改 c 项目的设置或属性 以便创建应运行此 c 代码的 bat 文件 将 C
  • 将 size_t 变量添加到指针

    我想向指针添加 size t 类型 有些像这样 void function size t sizeA size t sizeB void pointer pointer malloc sizeA pointer pointer sizeB
  • 使用 .NET Core Razor Pages 将文件下载到浏览器

    使用 ASP NET Razor Pages 我尝试将文件下载到浏览器 在页面 html 中 使用这样的链接效果很好 href DownloadableFiles testB csv download newname gt Download
  • LINQ 中的左外连接

    下面的代码不断给我一个错误消息 你调用的对象是空的 var partsWithDefaults from partsList1 in p join partsList2 in d on new PartNo partsList1 PartN
  • 如何避免函数的多重定义(Linux、GCC/G++、Code::Blocks)

    我有一个代码块项目 它使用许多不同的文件 通常是由其他程序员编写的 目前我遇到的情况是 我有两个不同的子项目 其中包含以相同方式命名的函数 比方说 F int x 因此 F int x 是在两个不同位置的两个源文件中定义的 并且它们有两个不
  • C# - 平移光标

    我正在 PictureBox 控件中实现大图像的平移 并且设置适当的方向平移光标没有问题 但是 我似乎找不到用于平底锅原点的图像 内部带有箭头的圆圈 我在哪里可以找到它 我觉得image您正在寻找的内容未包含在框架中 每个应用程序都使用自己
  • 如何让c代码执行hex机器代码?

    我想要一个简单的 C 方法能够在 Linux 64 位机器上运行十六进制字节码 这是我的 C 程序 char code x48 x31 xc0 include
  • 如何为单个函数设置 ICC 属性“fp-model precision”,以防止关联优化?

    我正在实施卡汉求和 http en wikipedia org wiki Kahan summation algorithm 在支持 gcc47 gcc48 clang33 icc13 和 icc14 编译的项目中 作为该算法的一部分 我想

随机推荐

  • RH850学习笔记

    这是一篇关于瑞萨RH850系列单片机的心得 网上关于这方面的资料特别少 可能是使用的人较少的原因吧 由于工作的原因 这段时间接触了这款单片机 所以写下了这篇博客 希望能给大家一些帮助 R7F701023 1023F1L是我最早接触的瑞萨MC
  • 算法笔记——动态规划

    算法笔记 动态规划 动态规划是一个非常灵活的算法 动态规划本身不难 无非就是一个状态转移的过程 难点就在于我们该如何去定义 状态 而这就需要我们多做题来积累经验 这也是初学者遇到动态规划往往无从下手的原因 动态规划的核心在于状态和状态转移方
  • 设计模式-迭代器模式

    迭代器模式 1 迭代器模式介绍 迭代器模式是一种行为型设计模式 它提供了一种方法来访问聚合对象中的各个元素 而不暴露其内部表示 通过使用迭代器 客户端可以遍历一个聚合对象中的元素 而不必了解其内部实现 在迭代器模式中 定义了一个迭代器接口
  • Vue生命周期与自定义组件

    自定义组件 Element 组件其实就是自定义的标签 例如
  • vue3知识点:setup

    文章目录 二 常用 Composition API 1 拉开序幕的setup setup的两个注意点 本人其他相关文章链接 二 常用 Composition API 问题 啥叫 组合式API 答案 请看官方文档 https v3 cn vu
  • 【Android】获取手机的相关硬件信息

    今天在QQ群里聊天 一个哥们在某宝买到了一个运行内存16G的手机 当时我就吓尿了 所以有了写个程序把这个手机的实际内存读出来的想法 于是就有了今天这篇博客 所有的信息项如下图所示 由于我的测试机没有插手机卡 所以有的信息会显示为空 以下就是
  • Python中的random函数

    显示 显示结果 random模块实现了各种分布的伪随机数生成器 伪随机数 人类使用算法等方式 以一个基准 也被称为种子 常用的是时间戳 来构造一系列数字 这些数字的特性符合人们所理解的随机数 一旦算法和种子都确定 产生的随机数序列也是确定的
  • Bitlocker 关闭加密 CMD 用命令 亲测有效

    CMD 命令行 解密Bitlocker 已管理员身份运行cmd 解锁 manage bde unlock C Recovery 忽略 加锁 manage bde lock C 忽略 解密 manage bde off C 加密 manage
  • linux查看服务器配置信息

    服务器型号 root txs dmidecode grep System Information A9 egrep Manufacturer Product 操作系统 root txs cat etc redhat release Cent
  • 最经典的20个Spring Boot面试题,95%以上会被问到,不服来战

    非常热门的 20 个Spring Boot 技术面试中经常被问到的问题 1 Spring Boot 有哪些特点 Spring Boot 是 Spring 的扩展 它消除了设置 Spring 应用程序所需的样板配置 自动配置 这是 Sprin
  • QT:多进程

    标题 1 多进程 2 多线程 3 常用方法 1 多进程 1 创建进程对象 QProcess QProcess QObject parent nullptr 2 启动进程去执行另外一个程序 void QProcess start const
  • 文华软件登录显示请选择服务器,文华随身行 请先登入云服务器

    文华随身行 请先登入云服务器 内容精选 换一换 本节操作介绍切换虚拟私有云的操作步骤 仅支持单网卡切换虚拟私有云 切换虚拟私有云前如果重装 切换过云服务器的操作系统 请先登录云服务器 验证重装 切换时设置的密码或密钥是否注入成功 如果成功登
  • 自动精简配置(Thin provisioning )介绍

    自动精简配置 Thin provisioning 介绍 自动精简配置 有时也被称为 超额申请 是一中重要的新兴存储技术 本文定义了自动精简配置 并介绍它的工作原理 使用局限和一些使用建议 如果应用程序所使用的存储空间已满 就会崩溃 因此 存
  • STL map自定义排序规则

    文章目录 一 map自定义排序规则 1 默认排序规格 2 修改按key排序规格 3 修改按value排序规则 二 参考资料 一 map自定义排序规则 map中存储的是key value键值对 默认按照key值从小到大顺序排序 即map只能按
  • 转换blob类型的数据,然后进行下载各种文件

    转换blob类型的数据 然后进行下载各种文件 ress 返回的数据流 var blob new Blob ress type application vnd ms excel type这里表示xlsx类型 var link document
  • java中float f=1.1为什么不合法

    因为Java里带有小数点的数默认是double类型 所以1 1在这里是double类型 把他赋值给比他小的float类型就会出错 你想通过编译的话有3种方法改 double f 1 1 或者 float f 1 1f 或者 float f
  • linux配合php创建定时任务,linux创建PHP定时任务的实例

    linux创建PHP定时任务的实例 linux创建PHP定时任务 下面所有的前提是服务器存在PHP环境 首先创建一个php文件 示例内容如下 ch curl init 设置请求 curl setopt ch CURLOPT URL 写上要请
  • 信息安全技术 政务信息共享 数据安全技术要求

    声明 本文是学习GB T 39477 2020 信息安全技术 政务信息共享 数据安全技术要求 下载地址 http github5 com view 790而整理的学习笔记 分享出来希望更多人受益 如果存在侵权请及时联系我们 政务信息共享 数
  • opencv的CopyTo的用法

    用法1 深拷贝 A CopyTo B B 与 A 矩阵一模一样 改变任何一个 互不影响 用法2 掩膜操作 A CopyTo B M 把与M中非0像素 相同位置的A中像素copy到B中同一位置 M 必须是CV 8U 可以是单通道或多通道 可以
  • C++ 函数实参传递 (argument passing)

    C 函数实参传递 argument passing argument jum nt n 实参 parameter p r m t r n 形参 每次调用函数时都会重新创建它的形参 并用传入的实参对形参进行初始化 形参初始化的机理与变量初始化