2011-12-02 4 views
4

죄송합니다 보폭과 인덱스 작업은,이 배열D 동적 배열 초기화,

에 대한 3 배 질문했다

나는 (동적) 배열, D 진정으로 강력한 생각하지만, 다음 잠시 동안 날 귀찮게되었습니다 :

C++에서는 지정된 값으로 배열을 쉽게 할당 할 수 있지만 DI에서는 그렇게 할 수있는 방법을 찾지 못했습니다. 분명히 다음은 문제가되지 않습니다 :

int[] a = new int[N]; 
a[] = a0; 

하지만, 비효율적 보이는 라인부터 하나 a0으로 추천을 0으로 초기화하고 있습니다. D에서 다음과 비슷한 것을 할 수 있습니까?

int[] a = new int(a0)[N]; // illegal 

std.range에서 보폭을 사용할 때 내가 가진 또 다른 효율성 문제 :

import std.stdio; 
import std.range; 

struct S 
{ 
    int x; 

    this(this) 
    { 
     writeln("copy ", x); 
    } 
} 

void f(S[] s) 
{ 
} 

int main() 
{ 
    S[] s = new S[10]; 
    foreach (i, ref v; s) 
    { 
     v.x = i; 
    } 

    f(stride(s, 3)); // error 
    return 0; 
} 

가 확실히 나는 단순히 요소의 복사하지 않고 새로운 배열을 만들기 위해 보폭을 사용할 수 순진한 생각이었다? D에서 그렇게하는 방법은 없습니다. 맞습니까?

그래서 내가 가서 보폭이 반환로 배열 인 것처럼 시뮬레이션 등과 같은 f을 구현 :

f(s, 3); 

void f(S[] s, uint stride) 
{ 
    ref S get(uint i) 
    { 
     assert (i * stride < s.length); 
     return s[i * stride]; 
    } 

    for (uint x ...) 
    { 
     get(x) = ...; 
    } 
} 

인덱스 연산자를 사용하는 대신 얻을 작성하는 방법 (X)이있을 것 get[x]? 이렇게하면 strideing get 함수를 정적으로 mixin/include 할 수 있고 나머지 함수는 비슷하게 유지할 수 있습니다. 로컬 구조체가 함수 범위 변수에 액세스 할 수 없기 때문에 (즉, 왜?) 접근 방식에 관심이 있습니다.

답변

7

하지만 1 행은 0으로 초기화되고 2는 a0으로 초기화되므로 비효율적입니다. D에서 다음과 비슷한 것을 할 수 있습니까?

사용


std.array.uninitializedArray

S[] s = uninitializedArray!(S[])(N); 
s[] = a0; 
확실히 I이었다 내가 단순히 요소의 복사하지 않고 새로운 배열을 만들기 위해 보폭을 사용할 수 순진한 생각? D에서 그렇게하는 방법은 없습니다. 맞습니까?

함수 f은 무엇 stride 반환 다른 인수, 같은 S[] 있습니다.

f(array(stride(s, 3))); 

그러나 당신은 아마도 복사 피하고 싶은 :

void f(Range)(Range s) 
{ 
    foreach (item; s) 
     // use item 
} 

S[] s = new S[10]; 
f(s); // works 
f(stride(s, 3)); // works too 

는 다른 방법이 배열을 복사 할 수 있습니다 :이 문제를 해결하는 D의 방법은 f 함수가 그것을 템플릿을 만들어 모든 범위를 받아 들일 수 있도록하는 것입니다 배열이 크다면 전체 배열.


대신 지수 연산자 [X] 얻을하여 (x)를 얻을 작성하는 방법이있을 것인가? 이렇게하면 striding get 함수를 정적으로 mixin/include 할 수 있고 나머지 함수는 비슷하게 유지할 수 있습니다. 로컬 구조체가 함수 범위 변수에 액세스 할 수 없기 때문에 (즉, 왜?) 접근 방식에 관심이 있습니다.

독자적인 구조로 색인 연산자를 오버로드 할 수 있습니다.

이것은 실제로는 stride 기능이 작동하는 방식입니다. Ranges에 대해 읽어 보시기 바랍니다.

+0

읽어 주셔서 감사합니다. 어떤 구조에서는 약간의 성능 손실이 있지만 (아마도 나는 그들을 남용합니다.) 코드는 훨씬 깔끔하고 일반적인 것입니다. opIndex와 opIndexAssign의 차이점은 opIndex가 단순히 ref를 반환 할 수없는 이유는 무엇입니까? –

+0

성능 문제가 해결되었습니다. C lib의 배열을 포인터에서 Range로 변환하면 코드가 더 깨끗해진다. 속도 차이는 발견되지 않았습니다. –

+0

'void f (범위) (...)'는 제약을 받아야합니다. 'isInputRange'? –

1

당신이 .dup와 배열 (이 또한 슬라이스로 작동합니다) (의 복사본을 생성) 복제 할 수 있습니다 또는 당신이 (당신이 F 제네릭 할 수

int[] a=a0.dup; 
int[] b=[e1,e2,e3]; 

배열 이니셜 라이저를 사용하여 요소를 설정할 수 있습니다 보폭은()는 반복 할 수있는 구조체가 아닌 배열)

void f(Z)(Z s)if(isInputRange!Z){ 
    foreach(elem;s){ 
     //... 
    } 
} 

배열은 일부 메모리 블록에 대한 포인터 필드와 크기 필드 본질적으로 구조체 것을 기억을 반환

+0

a0이 값이면 dup 구성원이 존재하지 않습니다. 그리고 : int [] b = [a0, a0, a0, a0 ... (N times)];은 힘든 노동이다. 따라서 요소를위한 기본 생성자 이외의 다른 것을 사용하여 배열을 할당 할 수있는 방법은 없습니다 (예 : 구조체의 경우 동일한 값으로 int를 값으로 설정하는 등). –