std :: optional을 어떻게 사용해야합니까?
설명서를 읽고 있는데 그 기능 std::experimental::optional
에 대해 잘 알고 있지만, 언제 사용해야하는지 또는 어떻게 사용해야하는지 이해할 수 없습니다 . 이 사이트에는 아직 예제가 포함되어 있지 않으므로이 객체의 진정한 개념을 이해하기가 더 어렵습니다. 언제 std::optional
사용하는 것이 좋으며, 이전 표준 (C ++ 11)에서 발견되지 않은 것을 어떻게 보상합니까?
내가 생각할 수있는 가장 간단한 예는 다음과 같습니다.
std::optional<int> try_parse_int(std::string s)
{
//try to parse an int from the given string,
//and return "nothing" if you fail
}
대신 다음 서명에서와 같이 참조 인수를 사용하여 동일한 작업을 수행 할 수 있지만 사용 std::optional
하면 서명과 사용법이 더 좋아집니다.
bool try_parse_int(std::string s, int& i);
이것을 할 수있는 또 다른 방법은 특히 나쁘다 :
int* try_parse_int(std::string s); //return nullptr if fail
이를 위해서는 동적 메모리 할당이 필요하고 소유권 등이 걱정됩니다. 위의 다른 두 서명 중 하나를 항상 선호하십시오.
다른 예시:
class Contact
{
std::optional<std::string> home_phone;
std::optional<std::string> work_phone;
std::optional<std::string> mobile_phone;
};
대신 std::unique_ptr<std::string>
각 전화 번호에 대해 비슷한 것을 사용하는 것이 좋습니다 . std::optional
성능에 큰 데이터 지역성을 제공합니다.
다른 예시:
template<typename Key, typename Value>
class Lookup
{
std::optional<Value> get(Key key);
};
조회에 특정 키가 없으면 "값 없음"을 반환 할 수 있습니다.
나는 이것을 다음과 같이 사용할 수 있습니다 :
Lookup<std::string, std::string> location_lookup;
std::string location = location_lookup.get("waldo").value_or("unknown");
다른 예시:
std::vector<std::pair<std::string, double>> search(
std::string query,
std::optional<int> max_count,
std::optional<double> min_match_score);
이는 가능한 모든 조합 max_count
(또는 그렇지 않은) 을 취하는 4 개의 기능 과부하를 갖는 것보다 훨씬 더 의미가 있습니다 min_match_score
!
또한 제거 저주 "패스를 -1
위해 max_count
또는"패스는 제한하지 않으려면 " std::numeric_limits<double>::min()
에 대한 min_match_score
당신이 최소한의 점수를 원하지 않는 경우"를!
다른 예시:
std::optional<int> find_in_string(std::string s, std::string query);
쿼리 문자열이에 없으면 s
"no int
"를 원합니다. 누군가가이 목적으로 사용하기로 결정한 특별한 값이 아닙니다 (-1?).
추가 예제는 boost::optional
설명서를 참조하십시오 . boost::optional
그리고 std::optional
기본적으로 행동과 사용의 측면에서 동일합니다.
예를 들면, 새로 채택 된 논문 : N3672, std :: optional :
optional<int> str2int(string); // converts int to string if possible
int get_int_from_user()
{
string s;
for (;;) {
cin >> s;
optional<int> o = str2int(s); // 'o' may or may not contain an int
if (o) { // does optional contain a value?
return *o; // use the value
}
}
}
하지만 언제 사용해야하는지 또는 어떻게 사용해야하는지 이해할 수 없습니다.
API를 작성할 때 "반환이없는"값이 오류가 아님을 표현하려는 경우를 고려하십시오. 예를 들어, 소켓에서 데이터를 읽고 데이터 블록이 완료되면 구문 분석하여 반환합니다.
class YourBlock { /* block header, format, whatever else */ };
std::optional<YourBlock> cache_and_get_block(
some_socket_object& socket);
If the appended data completed a parsable block, you can process it; otherwise, keep reading and appending data:
void your_client_code(some_socket_object& socket)
{
char raw_data[1024]; // max 1024 bytes of raw data (for example)
while(socket.read(raw_data, 1024))
{
if(auto block = cache_and_get_block(raw_data))
{
// process *block here
// then return or break
}
// else [ no error; just keep reading and appending ]
}
}
Edit: regarding the rest of your questions:
When is std::optional a good choice to use
When you compute a value and need to return it, it makes for better semantics to return by value than to take a reference to an output value (that may not be generated).
When you want to ensure that client code has to check the output value (whoever writes the client code may not check for error - if you attempt to use an un-initialized pointer you get a core dump; if you attempt to use an un-initialized std::optional, you get a catch-able exception).
[...] and how does it compensate for what was not found in the previous Standard (C++11).
Previous to C++11, you had to use a different interface for "functions that may not return a value" - either return by pointer and check for NULL, or accept an output parameter and return an error/result code for "not available".
Both impose extra effort and attention from the client implementer to get it right and both are a source of confusion (the first pushing the client implementer to think of an operation as an allocation and requiring client code to implement pointer-handling logic and the second allowing client code to get away with using invalid/uninitialized values).
std::optional
nicely takes care of the problems arising with previous solutions.
I often use optionals to represent optional data pulled from configuration files, that is to say where that data (such as with an expected, yet not necessary, element within an XML document) is optionally provided, so that I can explicitly and clearly show if the data was actually present in the XML document. Especially when the data can have a "not set" state, versus an "empty" and a "set" state (fuzzy logic). With an optional, set and not set is clear, also empty would be clear with the value of 0 or null.
This can show how the value of "not set" is not equivalent to "empty". In concept, a pointer to an int (int * p) can show this, where a null (p == 0) is not set, a value of 0 (*p == 0) is set and empty, and any other value (*p <> 0) is set to a value.
For a practical example, I have a piece of geometry pulled from an XML document that had a value called render flags, where the geometry can either override the render flags (set), disable the render flags (set to 0), or simply not affect the render flags (not set), an optional would be a clear way to represent this.
Clearly a pointer to an int, in this example, can accomplish the goal, or better, a share pointer as it can offer cleaner implementation, however, I would argue it's about code clarity in this case. Is a null always a "not set"? With a pointer, it is not clear, as null literally means not allocated or created, though it could, yet might not necessarily mean "not set". It is worth pointing out that a pointer must be released, and in good practice set to 0, however, like with a shared pointer, an optional doesn't require explicit cleanup, so there isn't a concern of mixing up the cleanup with the optional having not been set.
I believe it's about code clarity. Clarity reduces the cost of code maintenance, and development. A clear understanding of code intention is incredibly valuable.
Use of a pointer to represent this would require overloading the concept of the pointer. To represent "null" as "not set", typically you might see one or more comments through code to explain this intention. That's not a bad solution instead of an optional, however, I always opt for implicit implementation rather than explicit comments, as comments are not enforceable (such as by compilation). Examples of these implicit items for development (those articles in development that are provided purely to enforce intention) include the various C++ style casts, "const" (especially on member functions), and the "bool" type, to name a few. Arguably you don't really need these code features, so long as everyone obeys intentions or comments.
참고URL : https://stackoverflow.com/questions/16860960/how-should-one-use-stdoptional
'Programing' 카테고리의 다른 글
다른 컨트롤러에서 지시어 컨트롤러의 메소드 호출 (0) | 2020.07.17 |
---|---|
어떤 i 값이 while (i == i + 1) {}을 영원히 반복합니까? (0) | 2020.07.17 |
Factory Girl에서 has_and_belongs_to_many 연관을 작성하는 방법 (0) | 2020.07.17 |
Factory Girl을 사용하여 클립 첨부 파일을 생성하는 방법 (0) | 2020.07.17 |
pip로 특정 버전의 패키지를 설치하는 방법은 무엇입니까? (0) | 2020.07.17 |