使用g ++的奇怪事情(也许还有其他编译器?):
struct Object {
Object() { std::cout << "hey "; }
~Object() { std::cout << "hoy!" << std::endl; }
};
int main(int argc, char* argv[])
{
{
Object myObjectOnTheStack();
}
std::cout << "===========" << std::endl;
{
Object();
}
std::cout << "===========" << std::endl;
{
Object* object = new Object();
delete object;
}
}
Run Code Online (Sandbox Code Playgroud)
用g ++编写:
===========
hey hoy!
===========
hey hoy!
Run Code Online (Sandbox Code Playgroud)
第一种类型的分配不构造对象.我错过了什么?
所以我一直在考虑PIMPL和堆栈分配.我一直在写一个库,并决定使用PIMPL隐藏该类的私有成员.这意味着我会有一个像这样声明的类
class Foo {
private:
class Handle;
std::tr1::shared_ptr<Handle> handle;
public:
Foo();
};
Run Code Online (Sandbox Code Playgroud)
这很直接.但是然后在构造函数中你这样做
Foo::Foo() : handle(new Handle()) {}
Run Code Online (Sandbox Code Playgroud)
因此,当使用我的库的人在堆栈上创建Foo时,他们实际上是在进行堆分配.这是使用PIMPL时必须要考虑的权衡吗?我想在构造函数旁边发出警告释放文档:"警告:这会导致堆分配"或者其他一些问题.
我的另一个想法是将所有暴露给实现的类作为纯虚拟接口和一大堆静态工厂方法返回智能指针.这也意味着堆分配,但没有技巧.
有什么想法或建议吗?我是否过度考虑使用我的图书馆的程序员?
由于SIMD,我正在尝试使用System.Numerics库制作带有4个双打的向量.所以我做了这个结构:
public struct Vector4D
{
System.Numerics.Vector<double> vecXY, vecZW;
...
}
Run Code Online (Sandbox Code Playgroud)
在这个阶段,我将其编码为128位SIMD寄存器.它工作正常,但当我想要这样的东西:
Vector4D* pntr = stackalloc Vector4D[8];
Run Code Online (Sandbox Code Playgroud)
我明白了:
不能取地址,获取大小,或声明指向托管类型的指针('Vector4D')
知道如何在System.Numerics.Vector中使用stackalloc吗?使用System.Numerics.Vector4(浮点精度)指针没有问题,但我需要双精度.
知道为什么'stackalloc'关键字接受可变长度?
如果该指令返回指向堆栈帧中分配的缓冲区的指针,编译器如何管理它?每次调用它来组织堆栈帧时,它都会在运行时重新编译该函数?
谢谢.
考虑以下方法(fiddle):
void test(Span<int> param)
{
//Fail, the stackalloc'ed buffer could be exposed.
param = stackalloc int[10];
}
void test2(Span<int> param)
{
//OK
Span<int> local = stackalloc int[10];
}
Run Code Online (Sandbox Code Playgroud)
我不明白为什么param = stackalloc int[10];会产生错误:
“Span”类型表达式的结果
stackalloc不能在此上下文中使用,因为它可能会暴露在包含方法之外
Span是一个ref struct但是(尽管有它的名字)它仍然是一个值类型,因此任何修改都param不会反映在调用者对象上。
我认为它param是一个具有初始值的局部变量,我不明白为什么test2可以编译,而test不能编译。
stackalloc int[10]in的返回值如何test逃逸方法的范围?
我刚刚发现stackallocC#的符号有一个令人难以置信的怪癖,请看下面的代码:
// int *p;
// p = stackalloc int[42]; // won't work!
// Error CS1525: Unexpected symbol `stackalloc' (CS1525)
int *p = stackalloc int[42]; //works
Run Code Online (Sandbox Code Playgroud)
我的意图是在这样的三元表达式中使用stackalloc:
int *p = size > 0xFFFFF ? (int*)Marshal.AllocHGlobal(size).ToPointer() : stackalloc int[size];
Run Code Online (Sandbox Code Playgroud)
令人意外的编译器罢工让我感到震惊.如果有人能对这种奇怪的行为有所了解,我真的很感激.我已经在mono和.net上进行了测试,但都没有效果.
你好我想弄清楚是怎么工作的.stackalloc所以C/C++来自我的知识(有限)你不能动态地在堆栈上分配内存,就像在这里:
C/C++ 例:
void Allocate(int length){
int vector[length]; //wont work
}
Run Code Online (Sandbox Code Playgroud)
然后C#进入游戏,您可以这样做stackalloc:
void Allocate(int length){
int []vector=stackalloc int [length];
}
Run Code Online (Sandbox Code Playgroud)
是不是分配在stack知道compile-time或者precompile-time(macros等)数组的大小有什么分配?C#如何管理这个"magic"?如何创建堆栈框架?
当delegate在C#中使用匿名s时,CLR将在堆上为已使用的变量生成本地的副本(例如,当前作用域中的变量).对于当前作用域的每个声明变量,这样的local将被放到堆上.
您可以在此示例中看到此行为:
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 5; i++)
ThreadPool.QueueUserWorkItem(delegate { execute(i); });
Thread.Sleep(1000);
Console.WriteLine();
for (int i = 0; i < 5; i++)
{
int j = i;
ThreadPool.QueueUserWorkItem(delegate { execute(j); });
}
Thread.Sleep(1000);
}
static void execute(int number)
{
Console.WriteLine(" * NUM=" + number.ToString());
}
}
Run Code Online (Sandbox Code Playgroud)
该程序的输出是(顺序可能在最后5个条目上有所不同,而在第一个条目上也可能得到低于5的数字):
* NUM=5
* NUM=5
* NUM=5
* NUM=5
* NUM=5
* NUM=0
* NUM=1
* NUM=2
* NUM=3
* …Run Code Online (Sandbox Code Playgroud) stackalloc ×8
c# ×5
c++ ×3
pointers ×2
.net-core ×1
c#-7.3 ×1
heapalloc ×1
lifetime ×1
low-level ×1
oop ×1
pimpl-idiom ×1
ref-struct ×1
simd ×1
stack-frame ×1
threadpool ×1