标签: pointers

C#内存管理:不安全的关键字和指针

C#中使用unsafe关键字使用指针会产生什么后果(正面/负面)?例如,什么是垃圾收集,性能增益/损失是什么,与其他语言手动内存管理相比,性能增益/损失是什么,危险是什么,在哪种情况下使用这种语言是合理的功能,编译时间更长......?

c# pointers memory-management unsafe keyword

33
推荐指数
3
解决办法
7510
查看次数

C++标准:解除引用NULL指针以获取引用?

我想知道C++标准对这样的代码的说法:

int* ptr = NULL;
int& ref = *ptr;
int* ptr2 = &ref;
Run Code Online (Sandbox Code Playgroud)

在实践中,结果是ptr2NULL,但我想知道,这只是一个实现细节还是在标准中明确定义?
在不同的情况下,取消引用NULL指针应该导致崩溃,但是在这里我取消引用它以获得由编译器作为指针实现的引用,因此实际上没有实际的解除引用NULL.

c++ null pointers reference

33
推荐指数
2
解决办法
3万
查看次数

何时返回C++中的指针,标量和引用?

我正在从Java转向C++,并且对语言的灵活性感到有些困惑.有一点是存储对象的方法有三种:指针,引用和标量(如果我理解正确,则存储对象本身).

我倾向于尽可能使用引用,因为它尽可能接近Java.在某些情况下,例如派生属性的getter,这是不可能的:

MyType &MyClass::getSomeAttribute() {
    MyType t;
    return t;
}
Run Code Online (Sandbox Code Playgroud)

这不会编译,因为t只存在于范围内,getSomeAttribute()并且如果我返回对它的引用,它将在客户端可以使用之前指出它.

因此,我有两个选择:

  1. 返回一个指针
  2. 返回一个标量

返回指针看起来像这样:

MyType *MyClass::getSomeAttribute() {
    MyType *t = new MyType;
    return t;
}
Run Code Online (Sandbox Code Playgroud)

这样做,但客户端必须检查此指针NULL才能确定,这是引用不必要的.另一个问题是调用者必须确保t解除分配,如果我可以避免它,我宁愿不处理它.

另一种方法是返回对象本身(标量):

MyType MyClass::getSomeAttribute() {
    MyType t;
    return t;
}
Run Code Online (Sandbox Code Playgroud)

这非常简单,正是我在这种情况下想要的东西:感觉就像一个引用,它不能为空.如果对象超出客户端代码的范围,则会将其删除.非常方便.但是,我很少看到有人这样做,这有什么原因吗?如果我返回标量而不是指针或引用,是否存在某种性能问题?

处理这个问题最常见/最优雅的方法是什么?

c++ scalar pointers reference

33
推荐指数
1
解决办法
1万
查看次数

我可以将2D数组视为连续的1D数组吗?

请考虑以下代码:

int a[25][80];
a[0][1234] = 56;
int* p = &a[0][0];
p[1234] = 56;
Run Code Online (Sandbox Code Playgroud)

第二行是否调用未定义的行为?第四行怎么样?

c++ arrays pointers multidimensional-array undefined-behavior

33
推荐指数
3
解决办法
6087
查看次数

从函数返回指针

我试图从函数返回指针.但我得到分段错误.有人请告诉代码有什么问题

#include<stdio.h>
int *fun();
main()
{
    int *ptr;
    ptr=fun();
    printf("%d",*ptr);

}
int *fun()
{
    int *point;
    *point=12;  
    return point;
}   
Run Code Online (Sandbox Code Playgroud)

c pointers segmentation-fault

33
推荐指数
2
解决办法
11万
查看次数

从指针访问[]运算符

如果我定义一个指向定义[]运算符的对象的指针,是否有直接的方法从指针访问此运算符?

例如,在下面的代码中,我可以通过使用指针的运算符直接访问Vec的成员函数(例如empty())->,但是如果我想访问[]运算符,我需要先获取对象的引用然后调用运算符.

#include <vector>

int main(int argc, char *argv[])
{
    std::vector<int> Vec(1,1);
    std::vector<int>* VecPtr = &Vec;

if(!VecPtr->empty())      // this is fine
    return (*VecPtr)[0]; // is there some sort of ->[] operator I could use?

return 0;
}
Run Code Online (Sandbox Code Playgroud)

我可能错了,但看起来做(*VecPtr).empty()的效率低于做VecPtr->empty().这就是我寻找替代品的原因(*VecPtr)[].

c++ pointers operators

33
推荐指数
2
解决办法
2万
查看次数

C++对非const的引用初始值必须是左值

我正在尝试使用引用指针将值发送到函数中,但它给了我一个完全外来类型的错误

#include "stdafx.h"
#include <iostream>

using namespace std;

void test(float *&x){

    *x = 1000;
}

int main(){
    float nKByte = 100.0;
    test(&nKByte);
    cout << nKByte << " megabytes" << endl;
    cin.get();
}
Run Code Online (Sandbox Code Playgroud)

错误:对非const的引用的初始值必须是左值

我不知道我必须做些什么来修复上面的代码,有人能给我一些关于如何修复代码的想法吗?谢谢 :)

c++ pointers reference

33
推荐指数
3
解决办法
7万
查看次数

指针的最快哈希函数是什么?

基于散列表的容器是非常快速的关联数组(例如unordered_map,unordered_set).

它们的性能高度依赖于用于为每个条目创建索引的哈希函数.随着哈希表的增长,元素会一次又一次地重新出现.

指针是简单类型,基本上是唯一标识对象的4/8字节值.问题在于,由于多个LSB为零,因此使用地址作为散列函数的结果是无效的.

例:

struct MyVoidPointerHash {
    size_t operator()(const void* val) const {
        return (size_t)val;
    }
};
Run Code Online (Sandbox Code Playgroud)

更快的实现是丢失一些位:

struct MyVoidPointerHash2 {
    size_t operator()(const void* val) const {
        return ((size_t)val) >> 3; // 3 on 64 bit, 1 on 32 bit
    }
};
Run Code Online (Sandbox Code Playgroud)

后者在大型应用程序上产生了10-20%的性能提升,该应用程序使用散列集和映射以及经常构建和清除的数万个元素.

有人可以为散列指针提供更好的方案吗?

功能需要是:

  1. 快速!并且必须很好地内联.
  2. 提供合理的分配,允许罕见的碰撞.

更新 - 基准测试结果

我运行了两组测试,一组用于int*和一个大小为4KB的类指针.结果非常有趣.

我用于std::unordered_set所有测试,数据大小为16MB,在一次new调用中分配.第一个算法运行了两次,以确保缓存尽可能热,并且CPU正在全速运行.

设置:VS2013(x64),i7-2600,Windows 8.1 x64.

  • VS2013默认哈希函数
  • HASH1: return (size_t)(val);
  • HASH2: return '(size_t)(val) >> 3;
  • Hash3(@BasileStarynkevitch): uintptr_t ad = (uintptr_t)val; return …

c++ hash performance pointers

33
推荐指数
4
解决办法
1万
查看次数

指向未指定大小的数组"(*p)[]"在C++中是非法的,但在C中是合法的

我刚刚发现这在C++中是非法的(但在C语言中是合法的):

#include <stdio.h>
#include <stdlib.h>
#define ARRAY_LENGTH(A) (sizeof(A) / sizeof(A[0]))

int accumulate(int n, const int (*array)[])
{
    int i;
    int sum = 0;
    for (i = 0; i < n; ++i) {
        sum += (*array)[i];
    }
    return sum;
}

int main(void)
{
    int a[] = {3, 4, 2, 4, 6, 1, -40, 23, 35};
    printf("%d\n", accumulate(ARRAY_LENGTH(a), &a));
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

它编译没有问题使用gcc -std=c89 -pedantic但无法编译使用g++.当我尝试使用它来编译它时,g++我收到以下错误消息:

main.cpp:5:37: error: parameter 'array' includes pointer to array of unknown bound …
Run Code Online (Sandbox Code Playgroud)

c c++ arrays pointers function

33
推荐指数
2
解决办法
4926
查看次数

提供可选参数的现代 C++ 方法

让我们采用以下函数声明:

void print(SomeType const* i);
Run Code Online (Sandbox Code Playgroud)

在这里,const*参数的性质i暗示了意图,即参数是optional,因为它可能是nullptr。如果这不是故意的,那么参数将只是一个const&. 交流可选的语义当然不是设计指针的初衷,但使用它们来这样做恰好在很长一段时间内都能正常工作。

现在,由于在现代 C++ 中通常不鼓励使用原始指针(并且应该避免使用std::unique_ptrstd::shared_ptr精确指示特定的所有权 -语义),我想知道如何正确指示函数参数的可选 -语义而不传递值,即复制,作为

void print(std::optional<SomeType> i);
Run Code Online (Sandbox Code Playgroud)

会做。

考虑了一段时间后,我想出了使用的想法:

void print(std::optional<SomeType const&> i);
Run Code Online (Sandbox Code Playgroud)

这实际上是最准确的。但事实证明std::optional 不能有引用类型。¹

另外,使用

void print(std::optional<SomeType> const& i);
Run Code Online (Sandbox Code Playgroud)

决不会是最优的,从那时起,我们将要求我们SomeType在向存在std::optional主叫侧的,可能再次(或相当可能)需要复制那里

问题:那么在不复制的情况下允许可选参数的现代方法是什么?在这里使用原始指针在现代 C++ 中仍然是一种合理的方法吗?


¹:具有讽刺意味的是,所描述的为什么std::optional不能有引用类型的原因(关于重新绑定或转发赋值的争议)不适用于const引用的std::optionals的情况,因为它们不能被分配。

c++ pointers optional-parameters optional semantics

33
推荐指数
3
解决办法
2684
查看次数