从函数C++返回数组
Return array from function C++
我是C++的新手,我有C#、Objective-C和JavaScript的经验。
目前,我正在尝试编写一个函数,它采用一个路径并返回一个目录列表(该路径上的所有文件和文件夹(。我在Ubuntu上做这件事。
到目前为止,这是我的代码,老实说,我很难理解双指针语法及其实现的目标,但这正是我在谷歌上搜索的结果…
int FileManager::GetDirectoryListing(char *path, dirent **directoryEntries)
{
// Debug output...
printf("Listing directory at %sn", path);
// Allocate memory for the directory entries
*directoryEntries = new dirent[MAX_FILES];
// Open the path we were provided
DIR *directory = opendir(path);
// A counter of how many entries we have read
int entryCount = 0;
// Make sure we were able to open the directory
if(directory) {
printf("Successfully opened directoryn");
// Read the first entry in the directory
struct dirent *directoryEntry = readdir(directory);
// While we have a directory entry
while(directoryEntry) {
// Debug output...
printf("%sn", directoryEntry->d_name);
// Copy the directory entry to the array of directory entries we will return
memcpy(&directoryEntries[entryCount], directoryEntry, sizeof(struct dirent));
// Increase our counter
++entryCount;
// Read the next directory
directoryEntry = readdir(directory);
}
// Close the directory
closedir(directory);
}
return entryCount;
}
然后我调用这个函数:
dirent *directoryEntries = NULL;
int numberOfEntries = FileManager::GetDirectoryListing(deviceRootPath, &directoryEntries);
printf("File Manager returned directory listing.n");
for(int i = 0; i < numberOfEntries; ++i) {
printf("Looping through directory entries, at index: %in", i);
printf("%sn", directoryEntries[i].d_name);
}
当它试图访问directoryEntries
中的第一个元素时,即第一次访问循环时,它处于锁定状态。
我知道我不明白双指针在做什么,在调用GetDirectoryListing
之后,我对directoryEntries
的结构也没有清晰的了解。
发生了什么,通过directoryEntries
循环的正确方式是什么?
此行
memcpy(&directoryEntries[entryCount], directoryEntry, sizeof(struct dirent));
应该是这样的:
memcpy(&(*directoryEntries)[entryCount], directoryEntry, sizeof(struct dirent));
或等效地:
memcpy(*directoryEntries + entryCount, directoryEntry, sizeof(struct dirent));
原因是directoryEntries
是指向数组的指针的指针。在内存中,它看起来是这样的:
+------------+
directoryEntries --> array_head --> | dirents[0] |
+------------+
| dirents[1] |
+------------+
| dirents[2] |
+------------+
| ... |
但您将其视为directoryEntries
是指向数组的指针,而事实并非如此:
WRONG! +------------+
directoryEntries --> | dirents[0] |
+------------+
| dirents[1] |
+------------+
| ... |
所以你把越界写入了你不拥有的内存,导致了未定义的行为。
您需要额外的间接级别的原因是,在C中,函数参数总是按值传递的。为了修改参数,您需要传入一个指向原始值的指针,这就是您正在执行的操作。你只需要记住,在处理指针时,你有一个额外的间接级别。
如果您使用C++而不是C,那么最好使用引用参数而不是指针,并且还应该使用std::vector<struct dirent>
。您不需要担心额外级别的间接性,内存管理是自动为您处理的。
*directoryEntries = new dirent[MAX_FILES];
如果目录数量大于MAX_FILES
怎么办?你怎么知道它不能大于MAX_FILES
?
我认为你应该用std::vector<dirent>
而不是dirent*
。许多问题将得到解决。
我会将功能实现为:
std::vector<dirent> FileManager::GetDirectoryListing(char *path)
{
std::vector<dirent> dirs;
DIR *directory = opendir(path);
if(directory) {
struct dirent *directoryEntry = readdir(directory);
while(directoryEntry) {
dirs.push_back(*directoryEntry); //push a copy of the original!
directoryEntry = readdir(directory);
}
closedir(directory);
}
return dirs;
}
现代编译器很可能会优化此代码,以避免复制返回值。这种优化被称为:
- 返回值优化(RVO((或命名RVO(
还要注意,directories.size()
会告诉您条目的数量。所以在呼叫站点,您可以简单地这样做:
std::vector<dirent> dirs = FileManager::GetDirectoryListing(deviceRootPath);
for(size_t i = 0; i < dirs.size() ; ++i)
{
std::cout << dirs[i].d_name << std:endl;
}
一般来说,更喜欢std::cout
而不是printf
,因为后者不安全!
您的错误在这一行:
memcpy(&directoryEntries[entryCount], directoryEntry, sizeof(struct dirent));
您的directoryEntries
是指向struct dirent
的指针。其中的每个条目都是指向struct dirent
的指针。您的"&"导致您复制到指针的地址,而这不是您想要的。您想要:
memcpy(directoryEntries[entryCount], directoryEntry, sizeof(struct dirent));
- 为什么 C++ 中的字符数组返回其项目而不是地址?
- C++ bool 数组返回 1 或 0 以外的值
- C++ ostream 从对象数组返回数据
- 类中的重载运算符 [],因此它可以从模板类中的数组返回对象
- 指向对象的指针数组返回jibberish
- 具有基本结构的结构数组返回错误的答案
- 数组返回乐趣 movie_check()
- C++从字符数组返回类型为T的指针
- C++-将数组返回到主函数,并将数组传递给另一个函数
- C++:如何通过异常处理从越界数组返回值
- 整数数组返回类型
- 从字符串流复制到 char * 数组返回为函数参数
- C++函数从对象数组返回对象的副本.这是默认行为吗?
- 8字节数组返回长(C#到C++)
- 向c#数组返回一个字符数组c++
- 从并行数组返回值,并在以后的函数中使用这些值
- 将c++中的浮点数数组返回给Python
- 如何在gsoap中使字符串数组返回值
- 将两个字符相乘并向数组返回int
- C++套接字 - 从结构数组返回单个地址信息