일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 백준#boj#16932#모양만들기
- 백준#boj#12755
- 백준#BOJ#1939#중량제한
- 백준#BOJ#12865#평범한배낭
- 백준#BOJ#14501#퇴사#브루트포스
- 백준#BOJ#2615#오목
- 백준#BOJ#8012#한동이는영업사원
- Today
- Total
순간을 성실히, 화려함보단 꾸준함을
memcpy에 string 형을 쓰면 안될까???? 본문
안녕하세염
이번글은 memcpy 함수를 사용할때 겪었던 경험을 풀려고 합니다.
https://www.acmicpc.net/problem/3085
이 문제를 풀때 배열을 복사하기 위해서 평소 사용도 안해본 memcpy 함수를 사용해봤습니다.
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
int n;
string board[50];
string cp_board[50];
void solve();
int go();
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t = 1;
while (t--)solve();
return 0;
}
void solve()
{
int dx[] = { -1,1,0,0 }, dy[] = { 0,0,-1,1 };
cin >> n;
for (int i = 0; i < n; i++)cin >> board[i];
int ans = 1;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
for (int d = 0; d < 4; d++) {
int tx = i + dx[d];
int ty = j + dy[d];
if (tx < 0 || tx >= n || ty < 0 || ty >= n)continue;
swap(board[i][j], board[tx][ty]);
ans = max(ans,go());
swap(board[i][j], board[tx][ty]);
}
}
}
cout << ans;
}
int go()
{
int ret = 0;
memcpy(cp_board, board, sizeof(board));
/*for (int i = 0; i < n; i++)
cp_board[i] = board[i];*/
for (int i = 0; i < n; i++) {
int cnt = 0;
//sort(cp_board[i].begin(), cp_board[i].end());
for (int j = 1; j < n; j++) {
if (cp_board[i][j - 1] == cp_board[i][j])
cnt++;
else {
ret = max(ret, cnt);
cnt = 0;
}
ret = max(ret, cnt);
}
}
/*for (int i = 0; i < n; i++)
cp_board[i] = board[i];*/
memcpy(cp_board, board, sizeof(board));
for (int i = 0; i < n; i++) {
int cnt = 0;
string str;
for (int j = 0; j < n; j++)
str.push_back(cp_board[j][i]);
//sort(str.begin(), str.end());
for (int j = 1; j < n; j++) {
if (str[j - 1] == str[j])
cnt++;
else{
ret = max(ret, cnt);
cnt = 0;
}
ret = max(ret, cnt);
}
}
return ret+1;
}
근데 로컬에서 출력할때 이상하다싶더니 제출하니 '메모리초과'가 발생하게 되버렸습니다.
그래서 공식 레퍼런스 문서를 찾다보니,
If the objects are potentially-overlapping or not TriviallyCopyable, the behavior of memcpy is not specified and may be undefined.
(potentially-overlapping 이거나 TriviallyCopyable이 아닌 경우에 memcpy 함수의 동작이 정의되지 않을 수 있습니다.)
라는 뜻인데, 여기서 대체 potentially-overlapping 과 TriviallyCopyable 이 뭘까요??
potentially-overlapping 단어를 선택해서 링크를 타고 들어가면 이런 글이 있습니다.
A subobject is potentially overlapping if it is a base class subobject or a non-static data member declared with the attribute
(하위 객체가 기본 클래스 하위 객체이거나 속성으로 선언된 비정적 데이터 멤버인 경우 잠재적으로 겹칠 수 있습니다.)
즉, 복사되는 메모리와 복사할 메모리가 겹칠 수도 있는 현상을 뜻합니다. memcpy 함수를 사용해서 복사를 할텐데 메모리 공간이 겹치면 안됨을 의미합니다.
사실 이 문제를 틀렸던 이유 중 하나는 바로 TriviallyCopyable 때문이었습니다.
역시 단어를 선택하고 링크를 타고 들어가면 친절하게 정의가 되어있습니다.
[https://en.cppreference.com/w/cpp/named_req/TriviallyCopyable]
핵심은 TriviallyCopyable 가 될 조건이 여러가지가 있는데 string형이 이 조건에 부합하지 않기 때문에 결국 TriviallyCopyable 이 될 수 없다라는 것 입니다.
그렇기 때문에 memcpy 에는 string 형을 사용할 수가 없습니다.
#include <bits/stdc++.h>
using namespace std;
int main()
{
if (is_trivial<string>())
cout << "Hello World!\n";
}
이 소스를 실행시키면 아무것도 출력이 되지 않음을 확인하실 수 있으실 겁니다.
결론 : memcpy를 사용할때 절대 string형은 사용하지 말자
'알고리즘,SQL > 백준,BOJ' 카테고리의 다른 글
[ boj : 14658 ] 하늘에서 별똥별이 빗발친다 (0) | 2022.02.03 |
---|---|
[ boj : 18223 ] 민준이와 마산 그리고 건우 (0) | 2022.02.01 |
[ boj : 2799 ] 블라인드 (0) | 2022.01.31 |
[ boj : 16507 ] 어두운 건 무서워 (0) | 2022.01.29 |
[ boj : 21608 ] 상어 초등학교 (0) | 2022.01.28 |