Meh*_*dad 11 c++ lifetime pointer-aliasing
std::vector<int> a;
a.push_back(1);
a.push_back(a[0]);
Run Code Online (Sandbox Code Playgroud)
我刚刚了解到上面的代码非常危险.
(如果不明白为什么,你并不孤单......对我来说也不是很明显.)
处理它的"标准"方式是什么?制作一个新变量,然后立即将其分配给某些东西对我来说似乎有点奇怪.有没有更好的方法来处理它?
你如何训练自己注意这样的混叠问题?你在寻找什么样的模式?我不知道这种情况; 当我restrict在C中学习关键字时,我才学会了别名,现在才明白这个问题究竟是什么.
我很乐意接受一个答案,但问题的第(2)部分似乎没有得到回答.我想知道人们使用什么策略来查找他们编写的代码中的别名错误.
到目前为止我提出的一个策略是避免在两个参数中传递相同的值.(在这种情况下,一个参数是隐式的,一个是显式的.)
是否还有其他容易注意到的事项需要注意和注意?
编辑:从技术上讲,如果包含的类型具有禁止复制构造函数,则标准不强制这是正确的.我不知道在任何情况下这都没有实现的任何实现,因为它需要产生两个实现,push_back当通用的实现在所有情况下同样有效.
别名是一般问题,但在这种特殊情况下不是.代码:
assert( v.size() > 0 );
v.push_back( v[0] );
Run Code Online (Sandbox Code Playgroud)
通过标准(C++ 03)保证通过异常保证是正确的(这是一个非常好的理由不实现自己的容器,你可能无法正确使用它们).特别是§23.1[lib.container.requirements]/10 dictattes:
除非另有规定(参见23.2.1.3和23.2.4.3)[ 注意:这两个引用是指
insert对deque和vector分别 ]本节满足以下附加要求中定义的所有容器类型:-如果一个异常由的push_back()或push_front()函数抛出,该函数具有没有影响.
重要的一点是,如果在操作中抛出任何异常,容器保持不变,这意味着没有迭代器失效,这反过来意味着原始的内存区域保持不变,直到保证没有异常将被抛出(除了意图双关语,析构函数).因为通常复制构造函数可以抛出,所以实现必须确保在销毁任何对象之前执行所有副本.
这在C++ 0x中变得更加明显,当对象不是从一个位置复制到另一个位置而是移动时.因为新元素的副本可能会抛出,所以必须在执行任何移动之前执行,否则您将处于原始容器中的某些对象已失效的情况下.
我想这会是安全的:
std::vector<int> a(1);
a.push_back(1);
a.push_back(int(a[0]));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
312 次 |
| 最近记录: |