- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我是 C++ 的新手,所以这可能是一个初学者问题。它考虑了做一些我怀疑相当普遍的事情的“适当”风格。
我正在编写一个函数,该函数在履行其职责时会在堆上分配内存以供调用者使用。我很好奇这个函数的好的原型(prototype)应该是什么样子。现在我有:
int f(char** buffer);
要使用它,我会写:
char* data;
int data_length = f(&data);
// ...
delete[] data;
但是,我将一个指针传递给一个指针这一事实提示我,我可能以错误的方式执行此操作。
有没有人愿意开导我?
最佳答案
在 C 中,这或多或少是合法的。
在 C++ 中,函数通常不应该这样做。你应该尝试使用 RAII以保证内存不会泄漏。
现在您可能会说“它怎么会泄漏内存,我就在那里调用 delete[]
!”,但是如果 // ...
抛出异常怎么办?线条?
根据函数的确切用途,您可以考虑多种选择。一个明显的方法是用 vector 替换数组:
std::vector<char> f();
std::vector<char> data = f();
int data_length = data.size();
// ...
//delete[] data;
现在我们不再需要显式删除,因为 vector 是在堆栈上分配的,当它超出范围时会调用它的析构函数。
我应该提一下,作为对评论的回应,上面的内容暗示了 vector 的拷贝,这可能会很昂贵。大多数编译器会,如果 f
功能不是太复杂,优化那个拷贝,这样就可以了。 (如果函数调用不频繁,开销将不会很重要无论如何)。但如果这没有发生,您可以将一个空数组传递给 f
通过引用函数,并且有f
将其数据存储在其中,而不是返回一个新 vector 。
如果返回拷贝的性能 Not Acceptable ,另一种选择是完全解耦容器的选择,并改用迭代器:
// definition of f
template <typename iter>
void f(iter out);
// use of f
std::vector<char> vec;
f(std::back_inserter(vec));
现在可以使用通常的迭代器操作(*out
引用或写入当前元素,++out
将迭代器向前移动到下一个元素)——更重要的是,所有标准算法现在都将工作。你可以使用 std::copy
例如,将数据复制到迭代器。这是标准库通常选择的方法(即,这是一个好主意;))当函数必须返回数据序列时。
另一种选择是让您自己的对象负责分配/解除分配:
struct f { // simplified for the sake of example. In the real world, it should be given a proper copy constructor + assignment operator, or they should be made inaccessible to avoid copying the object
f(){
// do whatever the f function was originally meant to do here
size = ???
data = new char[size];
}
~f() { delete[] data; }
int size;
char* data;
};
f data;
int data_length = data.size;
// ...
//delete[] data;
同样,我们不再需要显式删除,因为分配是由堆栈上的对象管理的。后者显然需要更多的工作,并且有更多的错误空间,所以如果标准 vector 类(或其他标准库组件)可以完成这项工作,则更喜欢它们。此示例仅在您需要根据您的情况进行定制的情况下使用。
C++ 中的一般经验法则是“如果您在 RAII 对象之外编写 delete
或 delete[]
,那么您就错了。如果您正在编写 new
或 `new [] 在 RAII 对象之外,你做错了,除非结果立即传递给智能指针”
关于c++ - 在堆上分配内存的函数原型(prototype) (C/C++),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1171923/
C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: ?
最近,我有一个关于工作预评估的问题,即使查询了每个功能的工作原理,我也不知道如何解决。这是一个伪代码。 下面是一个名为foo()的函数,该函数将被传递一个值并返回一个值。如果将以下值传递给foo函数,
CStr 函数 返回表达式,该表达式已被转换为 String 子类型的 Variant。 CStr(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CSng 函数 返回表达式,该表达式已被转换为 Single 子类型的 Variant。 CSng(expression) expression 参数是任意有效的表达式。 说明 通常,可
CreateObject 函数 创建并返回对 Automation 对象的引用。 CreateObject(servername.typename [, location]) 参数 serv
Cos 函数 返回某个角的余弦值。 Cos(number) number 参数可以是任何将某个角表示为弧度的有效数值表达式。 说明 Cos 函数取某个角并返回直角三角形两边的比值。此比值是
CLng 函数 返回表达式,此表达式已被转换为 Long 子类型的 Variant。 CLng(expression) expression 参数是任意有效的表达式。 说明 通常,您可以使
CInt 函数 返回表达式,此表达式已被转换为 Integer 子类型的 Variant。 CInt(expression) expression 参数是任意有效的表达式。 说明 通常,可
Chr 函数 返回与指定的 ANSI 字符代码相对应的字符。 Chr(charcode) charcode 参数是可以标识字符的数字。 说明 从 0 到 31 的数字表示标准的不可打印的
CDbl 函数 返回表达式,此表达式已被转换为 Double 子类型的 Variant。 CDbl(expression) expression 参数是任意有效的表达式。 说明 通常,您可
CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant。 CDate(date) date 参数是任意有效的日期表达式。 说明 IsDate 函数用于判断 d
CCur 函数 返回表达式,此表达式已被转换为 Currency 子类型的 Variant。 CCur(expression) expression 参数是任意有效的表达式。 说明 通常,
CByte 函数 返回表达式,此表达式已被转换为 Byte 子类型的 Variant。 CByte(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CBool 函数 返回表达式,此表达式已转换为 Boolean 子类型的 Variant。 CBool(expression) expression 是任意有效的表达式。 说明 如果 ex
Atn 函数 返回数值的反正切值。 Atn(number) number 参数可以是任意有效的数值表达式。 说明 Atn 函数计算直角三角形两个边的比值 (number) 并返回对应角的弧
Asc 函数 返回与字符串的第一个字母对应的 ANSI 字符代码。 Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。
Array 函数 返回包含数组的 Variant。 Array(arglist) arglist 参数是赋给包含在 Variant 中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则
Abs 函数 返回数字的绝对值。 Abs(number) number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回 Null;如果是未初始化变量,则返回 0。
FormatPercent 函数 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 FormatPercent(expression[,NumDigitsAfterD
FormatNumber 函数 返回表达式,此表达式已被格式化为数值。 FormatNumber( expression [,NumDigitsAfterDecimal [,Inc
我是一名优秀的程序员,十分优秀!