我试图找出在Visual C++中使用什么形式的别名分析.它也被称为指针分析,模型参考分析,点到分析或副作用分析,并且非常接近逃逸分析或形状分析(如果您已经看到这些术语被绑定).
如果有人知道MSDN讨论这种事情的地方,我可能会从那里找到我的方式.(我尝试过搜索,但如果你没有在那里花太多时间,MSDN似乎是难以理解的.)
compiler-construction optimization static-analysis pointer-aliasing visual-c++
我有一个接收指针数组的函数,如下所示:
void foo(int *ptrs[], int num, int size)
{
/* The body is an example only */
for (int i = 0; i < size; ++i) {
for (int j = 0; j < num-1; ++j)
ptrs[num-1][i] += ptrs[j][i];
}
}
Run Code Online (Sandbox Code Playgroud)
我想传达给编译器的是指针ptrs[i]不是彼此的别名,并且数组ptrs[i]不重叠.我该怎么办?我别有用心的是鼓励自动矢量化.
另外,有没有办法获得与__restrict__a的迭代器相同的效果std::vector?
我有一些代码,我已成功使用多年来实现"变体类型对象"; 也就是说,一个C++对象可以保存各种类型的值,但只使用(大约)尽可能多的内存作为最大的可能类型.该代码在精神上类似于tagged-union,但它也支持非POD数据类型.它通过使用char缓冲区,placement new/delete和reinterpret_cast <>来实现这种魔力.
我最近尝试在gcc 4.4.3(带-O3和-Wall)下编译这段代码,并得到了很多这样的警告:
warning: dereferencing type-punned pointer will break strict-aliasing rules
Run Code Online (Sandbox Code Playgroud)
从我读过的内容来看,这表明gcc的新优化器可能会生成'buggy'代码,我显然希望避免这种代码.
我在下面粘贴了我的代码的"玩具版"; 我可以对我的代码做些什么来使它在gcc 4.4.3下更安全,同时仍然支持非POD数据类型?我知道作为最后的手段,我总是可以使用-fno-strict-aliasing编译代码,但是如果代码在优化下没有中断会更好,所以我宁愿不这样做.
(注意,我想避免在代码库中引入boost或C++ 0X依赖,所以虽然boost/C++ 0X解决方案很有趣,但我更喜欢更老式的东西)
#include <new>
class Duck
{
public:
Duck() : _speed(0.0f), _quacking(false) {/* empty */}
virtual ~Duck() {/* empty */} // virtual only to demonstrate that this may not be a POD type
float _speed;
bool _quacking;
};
class Soup
{
public:
Soup() : _size(0), _temperature(0.0f) {/* empty */}
virtual ~Soup() {/* empty */} // virtual only to demonstrate that this …Run Code Online (Sandbox Code Playgroud) 我有一个与此类似的功能签名
void Mutliply(const MatrixMN& a, const MatrixMN& b, MatrixMN& out);
Run Code Online (Sandbox Code Playgroud)
矩阵类在内部有一个float* data;代表m x n组件的类.我想告诉编译器,a并且b不要对out矩阵进行别名,因此它不会执行大量的加载存储.
我该怎么做呢?我知道我可以传入指向函数签名的指针并用__restrict(在MSVC中)标记指针但是我想保留通过引用传递的对象的习惯用法,其中对象包含指向内存的指针.
我也知道这__restrict对象引用不起作用.
考虑这个假设的实现vector:
template<class T> // ignore the allocator
struct vector
{
typedef T* iterator;
typedef const T* const_iterator;
template<class It>
void insert(iterator where, It begin, It end)
{
...
}
...
}
Run Code Online (Sandbox Code Playgroud)
我们在这里面临一个微妙的问题:
有可能begin并且end在之后 引用同一向量中的项目where.
例如,如果用户说:
vector<int> items;
for (int i = 0; i < 1000; i++)
items.push_back(i);
items.insert(items.begin(), items.end() - 2, items.end() - 1);
Run Code Online (Sandbox Code Playgroud)
如果It不是指针类型,那我们就没事了.
但是我们不知道,所以我们必须检查它[begin, end)是否指向已经在向量内的范围.
但是我们怎么做呢?根据C++,如果它们不引用相同的数组,那么指针比较将是未定义的!
所以编译器可能会错误地告诉我们这些项不是别名,实际上它们确实是这样,给了我们不必要的O(n)减速.
一种解决方案是每次复制整个 …
我重新实现了QGraphicsView以使用鼠标滚轮事件缩放场景.该场景包含几个QGraphicsPixmapItem.wheel事件调用QGraphicsView :: scale(qreal sx,qreal sy)
一切都很完美,但渲染.当我缩小(场景变小)时,会出现锯齿.我尝试在重新实现的QGraphicsView构造函数中设置渲染提示如下:
ImageViewer::ImageViewer(QWidget * parent) :
QGraphicsView(parent)
{
setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::HighQualityAntialiasing);
}
Run Code Online (Sandbox Code Playgroud)
我仍然看到这些文物.我怎么能摆脱这个?
如果dot_product声明为
float dot_product(const float* restrict a, const float* restrict b, unsigned n);
Run Code Online (Sandbox Code Playgroud)
会打电话给
dot_product(x, x, x_len)
Run Code Online (Sandbox Code Playgroud)
根据C99标准,"未定义"?
编辑
x是一个指针,当然,指向sizeof(float) * x_len内存的字节,x_len是unsigned.这个问题是关于别名的.
我为我的 D3 图表创建了一个精简的JSFiddle。我使用以下解决方案使其具有响应性(使用 viewbox 和 preserveaspectratio): responsive D3 chart
当我调整窗口大小并使其变小时,一些网格线似乎消失并重新出现。我认为这在小分辨率下看起来很糟糕(例如 320x480 手机)。当窗口变小时,有没有办法保留我的网格线?
HTML代码:
<!--//d3 chart//-->
<div class="centre-div"></div>
Run Code Online (Sandbox Code Playgroud)
CSS 代码:
.centre-div {
margin: 0 auto;
max-width: 550px;
}
/* D3 chart css */
.axis path,
.axis line {
fill: none;
stroke: black;
shape-rendering: crispEdges;
}
.axis text {
font-family: sans-serif;
font-size: 11px;
}
Run Code Online (Sandbox Code Playgroud)
JS代码:
//function createScatterplot() {
//Width and height
var margin = {
top: 15,
right: 2,
bottom: 2,
left: 2
};
//define width and height as the …Run Code Online (Sandbox Code Playgroud) 如果有3个班级.A,B和C. B类扩展A,C类扩展B.
A类有等于方法:
public boolean equals(A other)
{...}
Run Code Online (Sandbox Code Playgroud)
B级有等于方法:
public boolean equals(B other)
{...}
Run Code Online (Sandbox Code Playgroud)
和C类有euals方法:
public boolean equals(Object other)
{...}
Run Code Online (Sandbox Code Playgroud)
主要有这些代码行:
A a = new A();
C c = new C();
a=c;
System.out.println(a.equals(c));
Run Code Online (Sandbox Code Playgroud)
我无法理解为什么正在执行A类的equals方法.
我知道重载方法是使用静态绑定绑定的.但是指向别名之后的"对象的C部分"并且方法等于C类.为什么不执行C类的equals方法呢?
引自C99标准:
6.5.2.3
5为了简化联合的使用,我们做了一个特殊的保证:如果一个联合包含几个共享一个共同初始序列的结构(见下文),并且如果联合对象当前包含这些结构中的一个,则允许检查它们中任何一个的共同初始部分,可以看到完整类型的联合声明.如果对应的成员具有一个或多个初始成员的序列的兼容类型(并且对于位字段,具有相同的宽度),则两个结构共享共同的初始序列.
这种情况有一个例子:
// The following code is not a valid fragment because
// the union type is not visible within the function f.
struct t1 { int m; };
struct t2 { int m; };
int f(struct t1 *p1, struct t2 *p2)
{
if (p1->m < 0)
p2->m = -p2->m;
return p1->m;
}
int g()
{
union
{
struct t1 s1;
struct t2 s2;
} u;
/* ... */
return f(&u.s1, &u.s2);
}
Run Code Online (Sandbox Code Playgroud)
我添加了一些更改:
#include <stdio.h> …Run Code Online (Sandbox Code Playgroud) pointer-aliasing ×10
c++ ×4
c ×3
pointers ×2
antialiasing ×1
c99 ×1
d3.js ×1
gcc ×1
java ×1
optimization ×1
polymorphism ×1
qt ×1
responsive ×1
struct ×1
svg ×1
type-punning ×1
unions ×1
visual-c++ ×1