在C#中使用unsafe关键字使用指针会产生什么后果(正面/负面)?例如,什么是垃圾收集,性能增益/损失是什么,与其他语言手动内存管理相比,性能增益/损失是什么,危险是什么,在哪种情况下使用这种语言是合理的功能,编译时间更长......?
我想知道C++标准对这样的代码的说法:
int* ptr = NULL;
int& ref = *ptr;
int* ptr2 = &ref;
Run Code Online (Sandbox Code Playgroud)
在实践中,结果是ptr2NULL,但我想知道,这只是一个实现细节还是在标准中明确定义?
在不同的情况下,取消引用NULL指针应该导致崩溃,但是在这里我取消引用它以获得由编译器作为指针实现的引用,因此实际上没有实际的解除引用NULL.
我正在从Java转向C++,并且对语言的灵活性感到有些困惑.有一点是存储对象的方法有三种:指针,引用和标量(如果我理解正确,则存储对象本身).
我倾向于尽可能使用引用,因为它尽可能接近Java.在某些情况下,例如派生属性的getter,这是不可能的:
MyType &MyClass::getSomeAttribute() {
MyType t;
return t;
}
Run Code Online (Sandbox Code Playgroud)
这不会编译,因为t只存在于范围内,getSomeAttribute()并且如果我返回对它的引用,它将在客户端可以使用之前指出它.
因此,我有两个选择:
返回指针看起来像这样:
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)
这非常简单,正是我在这种情况下想要的东西:感觉就像一个引用,它不能为空.如果对象超出客户端代码的范围,则会将其删除.非常方便.但是,我很少看到有人这样做,这有什么原因吗?如果我返回标量而不是指针或引用,是否存在某种性能问题?
处理这个问题最常见/最优雅的方法是什么?
请考虑以下代码:
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
我试图从函数返回指针.但我得到分段错误.有人请告诉代码有什么问题
#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) 如果我定义一个指向定义[]运算符的对象的指针,是否有直接的方法从指针访问此运算符?
例如,在下面的代码中,我可以通过使用指针的运算符直接访问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)[].
我正在尝试使用引用指针将值发送到函数中,但它给了我一个完全外来类型的错误
#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的引用的初始值必须是左值
我不知道我必须做些什么来修复上面的代码,有人能给我一些关于如何修复代码的想法吗?谢谢 :)
基于散列表的容器是非常快速的关联数组(例如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%的性能提升,该应用程序使用散列集和映射以及经常构建和清除的数万个元素.
有人可以为散列指针提供更好的方案吗?
功能需要是:
更新 - 基准测试结果
我运行了两组测试,一组用于int*和一个大小为4KB的类指针.结果非常有趣.
我用于std::unordered_set所有测试,数据大小为16MB,在一次new调用中分配.第一个算法运行了两次,以确保缓存尽可能热,并且CPU正在全速运行.
设置:VS2013(x64),i7-2600,Windows 8.1 x64.
return (size_t)(val);return '(size_t)(val) >> 3;uintptr_t ad = (uintptr_t)val;
return …我刚刚发现这在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) 让我们采用以下函数声明:
void print(SomeType const* i);
Run Code Online (Sandbox Code Playgroud)
在这里,const*参数的性质i暗示了意图,即参数是optional,因为它可能是nullptr。如果这不是故意的,那么参数将只是一个const&. 交流可选的语义当然不是设计指针的初衷,但使用它们来这样做恰好在很长一段时间内都能正常工作。
现在,由于在现代 C++ 中通常不鼓励使用原始指针(并且应该避免使用std::unique_ptr并std::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的情况,因为它们不能被分配。