在C++中返回指针
Returning a pointer in C++
我认为我的问题听起来很愚蠢,欢迎对我投反对票。如果您在C++中实现需要返回指针的方法,这样做是否安全?如果没有,为什么?
不是一个简单的问题。例如:返回指针的最佳方式。
理想情况下,应尽量避免返回带有副作用或义务的值。
// This may be ok, it implies no burden on the user.
Manager* GetManager();
// But what if the user decides to call delete on the value you return?
// This is not unusual in C code, but carries a hidden contract:
// I allocate - you free.
const char* GetFilename(int fd)
{
char* filename = malloc(256);
sprintf(filename, "/tmp/tmpfile.%d", fd);
return filename;
}
C++是关于封装和抽象的。您可以通过封装要返回的指针来编纂与使用者的协定。这里的想法是,不是公开指针,而是公开一个负责指针所有权的对象。事实上,该语言的最新版本已经通过 std::unique_ptr、std::shared_ptr 和 std::weak_ptr 为您执行此操作。
但一个粗略、简单的 RAII 示例可能是:
class StrDupPtr
{
char* m_alloc;
public:
StrDupPtr(const char* src)
: m_alloc(strdup(src))
{}
~StrDupPtr()
{
free(m_alloc);
}
operator const char* () const { return m_alloc; }
// etc.
};
你仍然在此处返回一个指针,但你已使用管理协定封装了它,并消除了最终用户管理资源的负担。
你不能总是避免它,当你不得不这样做时,是的,它可能很危险。
int* AllocateMeSomeMemory()
{
int* memory = malloc(4 * sizeof(int));
// here, have four ints.
return memory;
}
int main() {
int* memory = AllocateMeSomeMemory();
memory[42] = 0xDeath; // yeah, it's not a valid hex number, but that's not really the problem.
}
指针的另一个常见问题是,无法判断有多少人拥有指针。下面是一个人为的例子:
void transferItem(userid_t user1, userid_t user2, itemid_t item) {
Account* a1 = GetAccount(user1);
Account* a2 = GetAccount(user2);
if (a1 != a2) {
transferItemInternal(a1, a2, item);
}
delete a2;
delete a1; // Sorry Dave, I can't do that. How about a nice game of CRASH?
}
通常,a2 和 a1 会有所不同,但是当它们不是时......
指针的另一个常见故障模式是异步回调:
// ask the database for user details, call OnLoginResult with userObj when we're done.
void login(int socket, userid_t userId, passwordhash_t pass) {
User* userObj = GetUserObj(userId, socket);
Query* query = Database()->NewQuery("SELECT * FROM user WHERE id = ? AND password = ?", userId, pass);
Database()->Queue(query, OnLoginResult, userObj);
}
void OnDisconnect(int socket, int reason) {
User* userObj = GetUserBySocket(socket);
if (userObj) {
UnregisterUserObj(userObj);
delete userObj;
}
}
void OnLoginResult(void* param) {
User* userObj = static_cast<UserObj*>(param);
// all well and good unless the user disconnected while waiting.
...
}
是的。我假设你的意思是"分配和返回"一个指针。
通常具有初始化函数,这些函数将指针分配给某种类型的对象,然后初始化对象本身。然后,程序的不同部分将释放内存。
这总是取决于你在做什么。指针只是一个内存地址,因此它类似于简单地返回一个整数。你应该对指针以及如何正确实现它们做更多的研究
我觉得这个问题可能很快就会结束,但无论如何我都会尝试回答。
是的,它是"安全的",只要你小心。事实上,这是一种非常常见的做事方式,尤其是在与 C API 交互时。话虽如此,如果可以的话,最好避免这样做,因为C++通常会提供更好的选择。
为什么要避免它?首先,假设您有一个如下所示的方法:
MyStruct* get_data();
返回值是指向MyStruct
单个实例的指针,还是数组的开头?是否需要free()
返回的指针?或者也许你需要使用delete
?返回值是否可以NULL
,如果是,会发生什么?如果不查看文档,您将无法了解这些内容中的任何内容。而且编译器也无法知道,因此它无法以任何方式帮助您。
更好的选择:
如果要返回值数组,请使用std::array
(如果大小在编译时是固定的)或std::vector
(如果大小在运行时之前未知)。
如果尝试避免复制大型结构,请返回引用或 const 引用(如果可能)。这样,调用方就知道他们不会收到NULL
值。
如果你真的需要返回一个指针,那么考虑使用智能指针来代替——这将有助于你解决所有权问题。例如,std::shared_ptr
使用引用计数,std::unique_ptr
确保给定指针只有一个所有者。
- 在 const 函数中通过引用和指针返回之间的区别
- 指向 std::unrodered_map 中元素的指针返回'Read access violation'
- 为什么要为指针返回类型返回一系列字符?
- Visual C 运行时:Malloc将指针返回到已经使用的内存(包含实际字符串)
- 将原始指针返回到智能指针
- 从函数中的指针返回对象,例如链接列表
- 将指针返回使用New创建的数组数组
- 查找并将指针返回向量中的对象
- 函数可以将指针返回其自己的类型
- 指针返回值的地址
- 为什么静态指针返回函数中有一个"静态"键?
- 从弱指针返回类型返回共享指针
- 如何将C++引用和指针返回转换为 C++/CLR
- 从指针返回对象时出现意外的析构函数调用
- 阵列指针返回垃圾
- (C )当在同一类中调用时,污点指针返回正确的值,而从MAIN调用时为0
- C 从指针返回到成员功能
- 在构造函数以外的任何其他位置访问相机时,我的相机指针返回 null
- 从取消引用的指针返回原始指针
- 指针返回