我想知道哪两个更好地将这两个地址传递给指针。第一个数据交换是否在第二个数据交换中没有发生?第二个是更有效的方式吗?更具可读性?两者都一样吗?
版本1
void ptrFunction(int& arg)
{
int* ptr = &arg;
std::cout<<"The pointer's value:" << *ptr << "\n";
}
int main()
{
int x=5;
ptrFunction(x);
return 0;
}
版本2
void CallViaPointers(int *arg)
{
int *ptr = *arg;
std::cout << "The pointer's value: " << *ptr;
}
int main()
{
int x = 100;
CallViaPointers(&x);
return 0;
}
答案 0 :(得分:4)
就效率而言,两者几乎肯定会在幕后编译为相同的代码,因为引用通常被实现为自动解除引用的指针。从这个角度来看,这两种解决方案是等价的。
至于是否通过指针或引用传递,这实际上是一个取决于情况的判断调用。如果你要做的只是打印出一个指向整数的指针(正如你在这里所做的那样),那么指针传递会更有意义,因为它更明确地与你想要做的事情保持一致。通常,编写函数以使参数具有内部所需的类型。如果你需要一个指针 - 要么是因为你正在构建一个链接结构,要么是因为你正在进行某种内存分配 - 那么请使用一个指针。如果你正在处理多态类,那么传统上你会通过指针而不是引用来接受你的参数,尽管两者都有效。如果你正在接受一个堆栈分配的对象来尝试修改它,那么引用可以更清楚一点。并且,如果您处于必须使用引用的情况之一 - 例如,作为重载运算符,复制构造函数或赋值运算符的参数 - 那么当然要使用引用。可读性现在被低估了,但是努力拥有干净,可读,直观的代码绝对是值得的。
答案 1 :(得分:1)
性能方面,当然,它完全取决于实施。通常,它们将编译为相同的机器代码。这绝对是你不应该考虑优化的情况之一,除非你必须这样做。在大多数代码中,可读性更为重要。
至于可读性,我倾向于选择版本2,因为我希望我的函数的用户知道我将(或能够)修改他放在那里的任何东西,但是这个规则有例外(例如捕获异常或运算符重载时。)
答案 2 :(得分:1)
int *ptr = *arg;
应该是:
int *ptr = arg;
当不清楚参数将被用作其他地方的指针时,我发现引用参数比指针参数更具可读性。通常就是这种情况,并且通常封装参数的使用,因此调用者不关心实现细节。但是,您可能必须符合现有接口,并且可能使用指针作为迭代器 - 然后您“按值传递迭代器”(传递迭代器的常用方法)而不是“将指针传递给对象” “,即使该迭代器实际上是一个原始指针类型。 (其他类型的现有接口也是可能的。)
除了上述,个人偏好和允许空指针(你不能有空引用)之外,它们在各方面都是相同的。
答案 3 :(得分:1)
我会说这取决于功能的作用。 现在你的功能名称与它的功能不匹配。如果确实如此,那么它将被命名为(我错误地读了这个问题。但是,是的,它仍然取决于你的函数是什么。)print_pointer
并且很明显它应该直接使用指针。
假设您有一个打印指针的函数,如:
void print_pointer(void* ptr)
{
std::cout << ptr << std::endl;
}
编写此函数以获取引用,然后获取它的地址没有意义,因为您不需要对象,您需要指向对象的指针,并且null在此有效上下文。
但是,如果你需要一个对象,就像代码一样,你应该引用一个引用,因为指向该对象是一个实现细节;带有引用的界面清楚地记录了您需要引用的对象。
目前,版本2是已损坏,因为传递null会导致程序崩溃,但null是一个有效的指针值。如果不是这样,请不要宣传您想要指针值。要修复它,检查null并做一些清楚记录的事情,比如什么都没有或抛出异常。但最好将参数更改为引用,因为您将这些问题留给调用者,并且您的函数无论如何都能正常工作。
(如果某人有一个指向对象的指针,他们可以负责安全地解除引用它以将有效对象传递给你的函数。换句话说,使用引用是自我记录:“null在这里无效” 。)
表现无关紧要。
答案 4 :(得分:1)
它们是等价的,这可以通过编译和检查反汇编来验证 - 它与符号名称不同。
至于风格,它主要是个人偏好,但是有一种使用指针作为输出参数的常见模式。这是因为当你接受引用时,不清楚你正在调用的函数是否会修改它。 “Effective C ++”对输入参数使用const引用,对输出参数使用非const指针。我觉得这是明确合同的好方法。