我在一个简单的代码上测试时间,但我看不出差异。 在第一个块中,它的作用就像只传递指针一样,在第二种情况和第三种情况下,它的作用类似于按值而不是通过引用复制整个结构。 编辑::: 结构:
struct e{
vector<int> a;
};
此代码需要0秒:
void ola(e &a)
{
a.a[0] = 1;
a.a[9999] = 1;
}
int main()
{
e *a;
a->a.resize(10000000, 0);
a->a[0] = 2;
a->a[99999] = 2;
ola(*a);
cout << a->a[0] << " . " << a->a[99999] << endl;
letras.resize('z' - 'a' + 1);
string entrada;
}
这个需要0.15秒:
void ola(e &a)
{
a.a[0] = 1;
a.a[9999] = 1;
}
int main()
{
e a;
a.a.resize(10000000, 0);
a.a[0] = 2;
a.a[99999] = 2;
ola(a);
cout << a.a[0] << " . " << a.a[99999] << endl;
letras.resize('z' - 'a' + 1);
string entrada;
}
但不应该有任何区别。也许它是因为在汇编程序中它必须在传递时复制struct的所有值,所以我尝试了这个:
void ola(e *a)
{
a->a[0] = 1;
a->a[9999] = 1;
}
int main()
{
e a;
e* b;
a.a.resize(10000000, 0);
b = &a;
a.a[0] = 2;
a.a[99999] = 2;
ola(b);
cout << a.a[0] << " . " << a.a[99999] << endl;
letras.resize('z' - 'a' + 1);
string entrada;
}
在最后一个我只传了一个指向a的指针,它也需要0.15秒。为什么我会看到这种差异?
答案 0 :(得分:2)
正确的想法。描述您的代码并测试您的假设,但要确保代码实际符合您的期望,并且分析是准确的。
第一点:向量并不总是通过引用传递。编译器将尽其所能通过引用传递,删除或拉出任何一个类似的技巧,因为它的工作量较少,但是当它不能时,矢量将被复制。
第二点: 时序代码很棘手。太难以覆盖这里了。但天真的假设几乎总是错误的。一次运行是不够的。通常需要对许多次运行进行许多运行和统计分析。
我将忽略这样一个事实,即案例1由于未初始化的指针将其带入未定义的区域而无法工作。这只是一个侧面展示。
案例1:
void ola(e &a)
a
通过引用传递,实际上和字面上都在这里。除地址外,不会复制任何数据。
ola(*a);
取消引用 a
以满足引用的要求,因此我们使用a
处的值。 a
是指针的事实现在无关紧要。 ola
获得参考。
案例2:
void ola(e &a)
相同的原型。也通过引用传递。除地址外,不会复制任何数据。
ola(a);
a
通过引用传递。
案例3:
void ola(e *a)
再次通过引用传递,但这次引用是一个指针。除地址外,不会复制任何数据。
ola(b);
b
是指向a
的指针,ola
是指针。无需工作。 a
通过引用传递。
要通过值传递,OP必须写:
void ola(e a)
如果编译器感觉像这样可以进行复制。足够聪明的编译器会注意到ola
绝对没有副作用,修改并丢弃副本,并编译函数调用。这种天真的形象可能表现出惊人的高效性,因为没有任何事情发生。
答案 1 :(得分:1)
在第一个区块中,您使用的指针( a )在使用之前未初始化。 我怀疑你在帖子中忘记了部分代码。
此外,它还不清楚你想要做什么以及你想要什么时间?
答案 2 :(得分:0)
在做任何有用的事情之前,第一个程序可能会崩溃。指向内存中的无效位置。它应该是:
e *a = new e();
a->a.resize(10000000, 0);