나는'm 를 사용하여 외부 라이브러리는 어떤 시점에서 제게 원 포인터 배열의 정수 및 크기입니다.
지금 나는'd 같이 사용하는std::벡터
에 액세스하고 이러한 값을 수정 장소에 보다는 오히려 그들을 액세스 하는 것으로 원 포인터입니다.
여기에는 articifial 를 들어 설명하는 포인트:
size_t size = 0;
int * data = get_data_from_library(size); // raw data from library {5,3,2,1,4}, size gets filled in
std::vector<int> v = ????; // pseudo vector to be used to access the raw data
std::sort(v.begin(), v.end()); // sort raw data in place
for (int i = 0; i < 5; i++)
{
std::cout << data[i] << "\n"; // display sorted raw data
}
예상 출력:
1
2
3
4
5
그 이유는 내가 필요로 적용하는 알고리즘에서<알고리즘>
(정렬,swaping 요소 등). 에는 데이터입니다.
다른 한편으로의 크기를 변경하는 벡터 수 없을 것이 변경되었다,그래서push_back
,삭제
,`삽입은 필요하지 않습에서 작동하는 벡터입니다.
나를 구성할 수 있습 벡터 데이터를 기반으로 라이브러리에서 사용할 수정하는 벡터와 데이터를 복사하시는 라이브러리,그러나는 것 두 개의 완전한 복사본는'd 을 피하기 위해 같은 데이터로 설정 될 수 있다는 정말 큰일이다.
std::span
는 경우 사용할 수 있는 C++20,사용할 수 있[std::span
](https://en.cppreference.com/w/cpp/container/span 도)포인터 길이의 쌍는 사용자에게 맞으면 연속 순서의 요소입니다. 그것은 일종의std::string_view
,그리고 모두가std::span
과std::string_view
비유망,std::string_view
읽기 보기만 가능합니다.
에서 docs:
The 템플릿 클래스의 범위는 개체를 설명하기를 참조하십시오 인접 객체의 순서와의 첫 번째 요소는 순서 에 위치한다. 범위할 수 있습 중 하나는 정도에서는 용자 시퀀스의 요소가 알려져 있고,인코딩 유형,또는 동적 정도입니다. 그래서 다음과 같은 작동: ``c++
include
include<마스터는 모든>
include<알고리즘>
int main(){ int 데이터[] = { 5, 3, 2, 1, 4 }; std::span
s{데이터,5}; std::종(s.begin(),s.end()); for(자동 const i:s){ std::cout<<i<<"\n"; } return0; } Check it out[live][1] 이후`std::span`은 기본적으로 포인터 길이의,당신은 당신이 사용할 수 있는 다음과 같은 방법으로도:
c++ 실제로 매우 불만족스럽다.size=0; int*데이터=get_data_from_library(size); std::spans{데이터,크기}; ` **참고:**하지 않는 모든 컴파일러 지원
std::span. 검사 컴파일러를 지원하는[여기](https://en.cppreference.com/w/cpp/compiler_support). **업데이트** 할 수 없는 경우 사용하는 C++20,사용할 수 있[
gsl::span](https://github.com/microsoft/GSL 도)기본적으로 기본 버전의 C++표준's
std::span`.C++11 솔루션
제한이 있는 경우 C++11 일 기준,당신이 시도할 수 있습을 구현하 자신의 간단한
범위
클래스: ``c++ 템플릿<형태 T> 클래스 span{ Tptr_; std::sizet len; 공용: 범위(Tptr,std::sizet len)noexcept :ptr{ptr},len{len} {} T&operator[](int i)noexcept{ return*ptr[i]; } T const&operator[](int i)const noexcept{ return*ptr_[i]; }
std::sizet size()const noexcept{ 반 len; } Tbegin()noexcept{ 반 ptr_; } Tend()noexcept{ 반 ptr+len; } }; `` 체크아웃 C++11 버전라이브
문제는std::벡터
는 복사본을 만들기 위해 요소의 배열에서 당신은 그것을 초기화와 함께 그것의 소유권을 개체 포함되어 있습니다.
이를 방지하기 위해 사용할 수 있습니다조각개체에 대한 배열(즉,는 것과 비슷한std::string_view
이하std::string
). 당신이 쓸 수 있는 자신의array_view
클래스 템플릿을 구현하의 인스턴스가 구성되어를 복용하여 원 포인터 배열's 첫번째 요소를 배열 길이:
#include <cstdint>
template<typename T>
class array_view {
T* ptr_;
std::size_t len_;
public:
array_view(T* ptr, std::size_t len) noexcept: ptr_{ptr}, len_{len} {}
T& operator[](int i) noexcept { return ptr_[i]; }
T const& operator[](int i) const noexcept { return ptr_[i]; }
auto size() const noexcept { return len_; }
auto begin() noexcept { return ptr_; }
auto end() noexcept { return ptr_ + len_; }
};
array_view
지 않't 저장 array;그냥을 보유하고 포인터 배열의 시작 부분의 길이는 배열입니다. 따라서,array_view
체는 저렴한을 구성하고를 복사합니다.
이후array_view
제공begin()
andend()
회원 기능을 사용할 수 있는 표준 라이브러리에서 알고리즘은(예를 들어,std::종류
,std::찾기
,std::lower_bound
,etc.) it:
#define LEN 5
auto main() -> int {
int arr[LEN] = {4, 5, 1, 2, 3};
array_view<int> av(arr, LEN);
std::sort(av.begin(), av.end());
for (auto const& val: av)
std::cout << val << ' ';
std::cout << '\n';
}
출력:
1 2 3 4 5
(또는
gsl::span`)신구현을 위에 노출의 개념조각개체. 그러나,이후 C++20 을 직접 사용할 수 있습니다std::span
대신 합니다. 어떤 경우에도 사용할 수 있습니다gsl::span
이후 C++14.
때문에 알고리즘-라이브러리와 함께 작동 반복기를 유지할 수 있습니다.
여기에서 사용할 수 있는 원 포인터로 반복기. 그들은 지원 opertations 반복기를 지원(증가 비교에 대한 평등의 가치,etc.):
``
int*get_data_from_library(int&크기){ static int data[]={5,3,2,1,4};
size=5;
데이터는 반환; }
int main() { int 크기; int*데이터=get_data_from_library(size);
std::종(데이터,데이터+크기);
for(int i=0;i<size;i++) { std::cout<<data[i]><<"\n"; } } ``
데이
포인트 dirst 배열 구성원처럼 반복기 반환에 의해begin()
와데이터+크기
포인트의 요소를 한 후에 마지막 요소의 배열은 다음과 같이 반복기를 반환한end()
.
여기서 당신은사용할 수 있습니다 std::begin()
와std::end()
``
int main() { int data[]={5,3,2,1,4};//원의 데이터 라이브러리
std::종(std::을 시작(data),std::종료(data));//원시 데이터를 정렬 장소에서
for(int i=0;i<5;i++) { std::cout<<data[i]><<"\n";//디스플레이 정렬된 원시 데이터 } } ``
그러나 유지 하는 마음에만 이 경우,데이터는`부패하지 않은 포인터이기 때문에,그 길이는 정보가 없습니다.
당신이 얻을 수있는 반복기를 원 어레이 및에서 사용하는 알고리즘:
c++ int data[]={5,3,2,1,4}; std::종(std::을 시작(data),std::종료(data)); for(자가:데이터){ std::cout<<i<<std::할당 공개; }
로 작업하는 경우에는 원 포인터(ptr+크기),다음 사용할 수 있습니다 다음과 같은 기법:
c++ 실제로 매우 불만족스럽다.size=0; int*데이터=get_data_from_library(size); 자동차 b=데이터 자동차 e=b+크기; std::종(b,e); 한(그것은 자동=b;it!= e;그것을++){ cout<<*it<<할당 공개; }
UPD:
그러나,위의 예쁜 디자인이다. 라이브러리를 반환 우리에게 원 포인터리고 우리는't 알고 있는 근본적인 버퍼가 할당되고 사람을 무료니다.
일반적으로,발신자가 제공하는 버퍼링을 위한 함수를 채우는 데이터입니다. 는 경우에,우리는 미리 할당 벡터와 사용할 기본 버퍼
c++ std::vector<int>v; v. 크기 조정(256);//버퍼를 할당을 위해 정수 256 size_t 크기=get_data_from_library(v. 데이터를(),v.size()); //수 있는 실제 데이터입니다. 참고로 기억 realocations 또는 사본은 여기에서 이루어집니다. v. 크기 조정(size); std::종(v.begin(),v.end()); for(자가:v){ cout<<i<<할당 공개; }
할 때 사용하여 C++11 나 위에서 우리는 할 수 있습 get_data_from_library()에서 반환하는 벡터입니다. 감사를 이동하는 작업이 없을 것,메모리에 복사합니다.
이제 나는'd 같이 사용하는 std::벡터에 액세스하고 이러한 값을 수정 장소에서
당신은 할 수 없습니다. 는's 지 않 whatstd::벡터
이다.std::벡터
리 자신의 버퍼는 항상에서 획득 할당자. 그것은 결코의 소유권 또 다른 완충기(제외에서 또 다른 벡터의 동일한 타입)으로 구성되어 있습니다.
다른 한편으로는,당신은 또한지't 필요하기 때문에...
그 이유는 내가 필요로 적용하는 알고리즘에서<알고리즘>(정렬,swaping 요소 등). 에는 데이터입니다.
그는 알고리즘에서 작동 반복기. 포인터가 반복기를 포함하는 배열을 반환합니다 지't 필요 vector:
std::sort(data, data + size);
과는 달리는 기능 템플릿에서<알고리즘>
,몇 가지 도구와 같은 범위에 대한,std::작
/std::엔드
그리고 C++20 범위와 함께 작동하지 않습의 반복기 비록하는 동안,그들은 작업으로 용기와 같은 벡터입니다. 그것은 가능한 래퍼를 만들어 등에 대한 반복+크기는 대로 작동 범위 및 작동을 가진 이러한 도구입니다. C++20 을 소개합니다 이러한 래퍼로 표준 라이브러리:std::span
.
당신은 실제로수 있거의 사용std::벡터
이를 위해,우월적 지위를 이용하여 사용자 정의 할당자를 기능을하는 포인터를 반환하는 메모리를 선택하십시오. 는 것't 에 의해 보장되는 표준을 일(패딩,정렬,초기화는 반환되는 값이다;당신이'd 을 가지고 가야 고통을 할당할 때 처음 크기,그리고 비 프리미티브를'd 는 또한 필요가 해킹을 당신의 생성자),그러나 실제로 기능을 충분히 되었습니다.
절대로 적다. It's ugly,놀라,해키고 불필요합니다. 표준 라이브러리는's 는 알고리즘은이미작동하도록 설계되었으로뿐만 아니라 원로 배열과 벡터입니다. 다른 답변에 대한 정보입니다.
또 다른 좋은 제안에 대해std::span
에서 오는[태그:c++20]그리고gsl:span
,자신을 포함하여(라)범위
클래스 그때까지 충분히 쉽게 이미(무료 사본):
template<class T>
struct span {
T* first;
size_t length;
span(T* first_, size_t length_) : first(first_), length(length_) {};
using value_type = std::remove_cv_t<T>;//primarily needed if used with templates
bool empty() const { return length == 0; }
auto begin() const { return first; }
auto end() const { return first + length; }
};
static_assert(_MSVC_LANG <= 201703L, "remember to switch to std::span");
의 특별한 참고도 부스트 범위는 라이브러리[태그:부스트 범위]에 관심이 있다면 더 많은 일반적인 범위의 개념:https://www.boost.org/doc/libs/1_60_0/libs/range/doc/html/range/reference/utilities/iterator_range.html.
범위 개념도에 도착[태그:c++20]
당신이 사용할 수 있std::reference_wrapper
이후 사용 가능한 C++11:
#include <iostream>
#include <iterator>
#include <vector>
#include <algorithm>
int main()
{
int src_table[] = {5, 4, 3, 2, 1, 0};
std::vector< std::reference_wrapper< int > > dest_vector;
std::copy(std::begin(src_table), std::end(src_table), std::back_inserter(dest_vector));
// if you don't have the array defined just a pointer and size then:
// std::copy(src_table_ptr, src_table_ptr + size, std::back_inserter(dest_vector));
std::sort(std::begin(dest_vector), std::end(dest_vector));
std::for_each(std::begin(src_table), std::end(src_table), [](int x) { std::cout << x << '\n'; });
std::for_each(std::begin(dest_vector), std::end(dest_vector), [](int x) { std::cout << x << '\n'; });
}
다른 사람들이 지적으로,std::벡터
있어야 합니다 기본 메모리(의 짧은 듣는 사용자 정의 할당자)그래서 수 있't 를 사용합니다.
다른 사람들도 좋 c++20's 범위,그러나 분명히 필요로 하는 c++20.
내가 권하고 싶span-litespan. 을 인용하는's 자막:
span lite-C++20 같은 범위에 대한 C++로 98,C++11 그 후에 단일 파일의 헤더에만 라이브러리
제공하는 비유와 가변 전망(로에 당신을 변화시킬 수 있는 요소와 그들의 순서만 그들을 삽입)및 따옴표가 말하는 때에는 없는 종속성과 작품에서 가장 컴파일러입니다.
귀하의 예:
#include <algorithm>
#include <cstddef>
#include <iostream>
#include <nonstd/span.hpp>
static int data[] = {5, 1, 2, 4, 3};
// For example
int* get_data_from_library()
{
return data;
}
int main ()
{
const std::size_t size = 5;
nonstd::span<int> v{get_data_from_library(), size};
std::sort(v.begin(), v.end());
for (auto i = 0UL; i < v.size(); ++i)
{
std::cout << v[i] << "\n";
}
}
인쇄
1
2
3
4
5
이것도 추가 상승하면 어느 날 당신은 스 c++20,당신이 할 수 있어야를 교체 이nonstd::span
와std::span
.