这是一个智能指针:std::shared_ptr<char> p(new char[size])表示填充原始二进制文件内容的数组.在整个数组从文件复制到RAM之后(并且仅在之后),我可以解析它,在此期间我检索一些头信息(几个第一个dwords).然后是实际数据.
在没有提供更多上下文的情况下,将所提到的共享指针设置为实际数据开头的新地址非常方便.该地址仍处于已分配的内存中.但如何设置而不失去它?
一个问题是(是/否):是否可以设置p偏移主流指针,而无需调用数据删除?
这个问题基于我发现监控可能内存泄漏的代码,因此它包含一些您可能不希望在常规程序中看到的代码,例如排序指针。
但是,我看到设置了一个指针nullptr,然后将该指针与最大地址进行比较。是否由 C++ 标准保证nullptr总是小于其他指针operator<?
比方说,我有一个类Derived从类派生Base而sizeof(Derived) > sizeof(Base).现在,如果分配一个这样的数组Derived:
Base * myArray = new Derived[42];
Run Code Online (Sandbox Code Playgroud)
然后尝试使用访问n-th对象
doSomethingWithBase(myArray[n]);
Run Code Online (Sandbox Code Playgroud)
然后,由于Base从无效位置访问,这可能(但不总是)导致未定义的行为.
这种编程错误的正确术语是什么?它应该被视为对象切片的情况吗?
以下代码(跨子对象边界执行指针运算)是否具有明确定义的行为,适用T于它编译的类型(在C++ 11中,不一定必须是POD)或其任何子集?
#include <cassert>
#include <cstddef>
template<typename T>
struct Base
{
// ensure alignment
union
{
T initial;
char begin;
};
};
template<typename T, size_t N>
struct Derived : public Base<T>
{
T rest[N - 1];
char end;
};
int main()
{
Derived<float, 10> d;
assert(&d.rest[9] - &d.initial == 10);
assert(&d.end - &d.begin == sizeof(float) * 10);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
LLVM在内部向量类型的实现中使用上述技术的变体,该内部向量类型被优化以最初将堆栈用于小型阵列,但是在初始容量上切换到堆分配的缓冲区.(之所以做这种方式是不是从这个例子清楚,但显然是要减少模板代码膨胀,这是更清楚,如果你去翻代码.)
注意:在任何人抱怨之前,这并不是他们正在做的事情,可能是他们的方法比我在这里给出的标准更符合标准,但我想询问一般情况.
显然,它在实践中有效,但我很好奇,如果标准中的任何内容保证是这样的话.考虑到N3242/expr.add,我倾向于拒绝.
当减去指向同一数组对象的元素的两个指针时,结果是两个数组元素的下标的差异...此外,如果表达式P指向数组对象的元素或者指向最后一个元素的元素对于数组对象,并且表达式Q指向同一数组对象的最后一个元素,表达式((Q)+1) - (P)具有与((Q) - (P))+ 1相同的值,并且as …
我很擅长使用C++,并且没有掌握语言的所有复杂性和细微之处.
在C++ 11中向任何类型的指针添加任意字节偏移量的最便携,正确和安全的方法是什么?
SomeType* ptr;
int offset = 12345 /* bytes */;
ptr = ptr + offset; // <--
Run Code Online (Sandbox Code Playgroud)
我在Stack Overflow和Google上找到了很多答案,但他们都提出了不同的建议.我遇到的一些变种:
ptr = (SomeType*)(((char*)ptr) + offset);
Run Code Online (Sandbox Code Playgroud)演员unsigned int:
ptr = (SomeType*)((unsigned int)ptr) + offset);
Run Code Online (Sandbox Code Playgroud)ptr = (SomeType*)((size_t)ptr) + offset);
Run Code Online (Sandbox Code Playgroud)"大小size_t并且ptrdiff_t总是与指针的大小一致.因此,这些类型应该用作大型数组的索引,用于存储指针和指针算术." - 关于 CodeProject上的size_t和ptrdiff_t
ptr = (SomeType*)((size_t)ptr + (ptrdiff_t)offset);
Run Code Online (Sandbox Code Playgroud)或者像之前的那样,但是intptr_t代替的size_t是签名而不是签名的:
ptr = (SomeType*)((intptr_t)ptr + (ptrdiff_t)offset);
Run Code Online (Sandbox Code Playgroud)仅转换为intptr_t,因为offset已经是有符号整数而intptr_t …
考虑到你可以(不能想出一个很棒的方法,但是)操作Go中的指针,是否有可能像在C中那样执行指针运算,比如迭代一个数组?我知道这些日子循环对于那种事情来说很好但是我只是好奇它是否可能.
C++标准[sec 5.7]说:
如果指针操作数和结果指向相同的数组对象,或一个过去的数组对象的最后一个元素的元素两者,所述评估也不得产生溢出; 否则,行为未定义.
那么,我是否正确地假设其他类型的指针比数组未定义?
例如:
int a = 0;
vector<int> v(&a, (&a)+1);
Run Code Online (Sandbox Code Playgroud)
上面的代码片段编译并且工作正常(使用g ++),但它是否有效?
我在OpenGL VBO实现中看到了以下宏:
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
//...
glNormalPointer(GL_FLOAT, 32, BUFFER_OFFSET(x));
Run Code Online (Sandbox Code Playgroud)
你能提供一下这个宏的工作原理吗?可以用功能替换吗?更确切地说,递增NULL指针的结果是什么?
以下代码打印一个正方形'*'字符:
int m = 5; int n=5;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
std::cout << "*" << " \n"[j==5];
Run Code Online (Sandbox Code Playgroud)
输出:
* * * * *
* * * * *
* * * * *
* * * * *
* * * * *
Run Code Online (Sandbox Code Playgroud)
我的问题是关于这个 " \n"[j==5]部分.有谁知道这个语法究竟是如何工作的?
c++ ×8
pointers ×6
arrays ×2
c ×2
c++11 ×2
go ×1
inheritance ×1
null ×1
nullptr ×1
opengl ×1
shared-ptr ×1
terminology ×1